Under the Hood · Nº 13

Under the Hood

A field guide to machine learning beyond the chat window

You ship with AI daily, but the machinery under it — loss, gradients, embeddings, the test set — still arrives wrapped in vendor metaphor. This course replaces the metaphor with mechanism: enough of how learning from data actually works to price a claim, spot a leak, and interrogate a benchmark. Not to train models — to be un-snowable about them.

Module 01 Learning as compression

Almost every bad decision a product manager makes about machine learning traces back to the same import error: the word learning arrives carrying its human meaning, and nobody unloads it at the door. Once a model is imagined as a student, everything downstream distorts — a system that scores well on material it has already seen looks like it understands, a vendor's talk of a proprietary optimizer sounds like a moat, and a model with more parameters sounds smarter the way a person with more education sounds smarter.

This module replaces the metaphor with the mechanism, one level below the popular account and no further. A model is a function with adjustable numbers. A loss function measures how wrong its outputs are. Gradient descent nudges the numbers downhill against that measure, over and over. That is the whole engine. What you gain from holding it precisely is the ability to ask the two questions that price any ML claim: what exactly is being minimized, and on what data was the minimizing measured.

What a model actually is

A model is a function with dials on it. You hand it an input, it returns an output, and its behavior is governed by a set of numbers — the parameters, or weights — that a programmer never wrote by hand. In ordinary software, a developer states the rule: if score > 92 and price < 60: recommend. In a learned system, the shape of the rule is fixed in advance and the numbers inside it are chosen by an optimization procedure that has seen examples.

Take the toy problem this course will keep returning to: predicting how a particular member of a wine club will rate a bottle. Start with the simplest possible parameterization — a weighted sum of a few features:

predicted_rating = w1*critic_score + w2*price + w3*years_in_bottle + b

There are four numbers here (three weights and an intercept). Training means searching for the four numbers that make the predictions closest to the ratings members actually gave. Nothing in that sentence requires intelligence, intention, or understanding; it requires a definition of closest and a procedure for searching. A frontier language model differs from this toy in that it has hundreds of billions of parameters arranged in a far richer functional form, and its inputs are token sequences rather than three columns. It does not differ in kind.

The load-bearing idea

Training does not install knowledge into a model the way you load a database. It searches a space of numbers for a setting that scores well against a measurement you chose. Everything you can honestly say about a trained model is downstream of two things: the measurement, and the data it was measured on.

This is why the productive question in a vendor meeting is never "how does the model work." It is "what were the labels." A model is a compressed summary of the examples it was fit to, filtered through the objective it was scored against. If you know both, you can predict most of its failures before you see one.

Loss: the objective made measurable

You cannot search for good parameters until good is a number. The loss function is that number: it takes the model's predictions and the true answers and returns a single scalar that training will try to make small. For the rating predictor, the default choice is squared error — average the squared gap between predicted and actual rating across all training examples:

loss = mean( (predicted_rating - actual_rating)^2 )

Squaring is not a formality. It declares that one prediction off by 4 points is worse than four predictions off by 1 point each — 16 versus 4. That is a value judgment about which mistakes hurt, and it was made by whoever chose the loss, which in most organizations is a machine learning engineer under deadline, not the person accountable for the product.

Worked example

The wine club's recommender minimizes squared rating error and gets very good at it. In the members' ratings, the difference between a predicted 91 and an actual 88 contributes the same 9 to the loss as the difference between a predicted 78 and an actual 81. But those two errors are nothing alike in the business: the first sends a member a bottle they mildly dislike, and the second denies them a bottle they would have loved. Neither is catastrophic. The catastrophic case — recommending a bottle a member finds genuinely offensive, flaws and all — is a rare, extreme error that squared loss under-weights precisely because it is rare. The fix is not a better optimizer. It is a loss that scores a predicted-91/actual-62 disaster far more heavily than the arithmetic gap suggests, or a reframing of the task from rating prediction to a ranking or a hard exclusion rule.

Read this way, choosing a loss is a policy act with the same structure as choosing a penalty schedule. In a fraud screen, whether you weight a missed fraud at 10 times a false alarm or at 500 times is not a modeling detail — it fixes the operating posture of the entire product, and it is legible in one line of the training code. Ask for that line.

When it misleads

The loss the model minimizes is rarely the thing the business wants. A recommender minimizes rating error but the business wants sustained subscription; a support classifier minimizes cross-entropy but the business wants resolved tickets. This gap — call it the proxy gap — is not a defect to be eliminated, because the thing you truly want is usually unmeasurable at training time. It is a risk to be named, bounded, and monitored. A team that cannot articulate its proxy gap has not thought about it.

Gradient descent: downhill in a million dimensions

Given a loss, how do you find the parameters that minimize it? For the four-parameter wine model you might imagine trying combinations at random, but that strategy dies immediately at scale: a model with a million parameters has a search space no enumeration can touch. Gradient descent replaces search with a local rule that is almost embarrassingly simple.

Freeze every parameter but one and ask: if I increase this weight a hair, does the loss go up or down, and how fast? That slope is the gradient with respect to that weight. Now step the weight a small distance in the downhill direction. Do this for every parameter at once, on a batch of examples, then repeat with the next batch. That is the entire training loop. The learning rate is the size of the step.

A one-dimensional loss curve with gradient-descent steps walking downhill toward the minimum, and a dashed path showing a too-large learning rate overshooting and divergingvalue of one weightlossbig step: steep slopesmaller steps: slope flattensminimum — training converges herelearning rate too large: overshoots, loss climbs
Figure 1.1 — Downhill, one step at a time. Each dot is a weight value; each arrow is one update, sized by the local slope times the learning rate. Steps shrink automatically as the curve flattens, which is why training slows near a minimum. The dashed path is the classic failure: a step size larger than the valley is wide sends the weight past the bottom and up the far wall, and each successive overshoot is worse — loss rises instead of falling.

Two failure modes fall straight out of the picture. A learning rate that is too large overshoots the valley and the loss diverges, often within a handful of updates; you see it as a loss curve that climbs to infinity or produces NaN. A learning rate that is too small converges honestly but consumes a training budget you do not have, and can stall in a shallow dip well above the good solutions. In practice, teams schedule the rate — larger early, decayed later — which is exactly the intuition the diagram gives you.

The dimensionality caveat, stated once

Figure 1.1 draws one weight on a two-dimensional page. A real model varies millions to billions of weights simultaneously, and that surface has no faithful picture. The one-dimensional intuition survives the trip — the update rule is per-weight and identical — but two things about high dimensions are worth knowing: local minima are much less of a practical problem than the picture suggests, and the surface has vast flat regions and narrow ravines that motivate the optimizer refinements (momentum, adaptive rates) you will hear named. Those refinements change the step, never the idea.

The training loop as a cycle: batch of examples, forward pass, loss computed, gradients, weight update, repeatBatch64 labeled examplesForward passmodel makes predictionsLossone number: how wrongGradientsslope per weightUpdatestep downhill x ratenext batch —repeat 10,000s of timesOne pass over allbatches = one epoch.Typical run: 3–50epochs.
Figure 1.2 — The training loop, in full. Five steps repeated until the budget or the patience runs out: take a batch, predict, measure the loss, compute each weight's slope against that loss, step every weight downhill. Nothing else happens during training. The loop count is large — tens of thousands of updates is ordinary — which is why compute is the cost driver and why the optimizer itself is commodity engineering.

Generalization versus memorization: compression as the test

Here is the fact that makes the whole rest of the course necessary. A model with enough capacity can drive its training loss to zero on any dataset — including a dataset whose labels were assigned by coin flip. It does this not by discovering structure but by storing the answers. With more parameters than training examples, that storage is trivially available.

So there are two ways to score perfectly on data you have seen. One is generalization: the model found regularities that compress the data — old-world reds with high acidity and modest alcohol get rated well by this member — and those regularities extend to bottles it has never encountered. The other is memorization: the model stored a lookup table and extends to nothing. On the training data, these look identical. Byte for byte, metric for metric, identical.

The compression framing is the useful one. A model that genuinely learned has represented ten thousand ratings in far fewer effective bits than the ratings themselves, and the compression is only possible because there was structure to exploit. A model that memorized has spent bits proportional to the data. Compression is evidence of understood structure — which is also why a model that is too small for its task underfits: it lacks the bits to hold even the real regularities.

The load-bearing idea

Performance on data the model was trained on carries almost no information about whether it learned anything. Only performance on data it has never touched can distinguish compression from lookup. Every evaluation practice in the next module is a defense of that one untouched sample.

From your other life

You already have the instinct from litigation. A witness who recites a prepared narrative flawlessly has demonstrated preparation, not knowledge; the test that separates the two is cross-examination on material the preparation did not cover. Training accuracy is direct examination. The holdout set is cross. Module 2 is about protecting your right to conduct one.

Module 02 Overfitting, leakage, and the test set

Module 1 ended on an uncomfortable fact: a model can score perfectly on data it has seen without having learned anything, and nothing about the training process reveals which happened. This module is about the machinery built to resolve that — and about the many ordinary, well-intentioned ways that machinery gets quietly disabled.

The stakes are practical. Nearly every ML project that dies in production dies here: the offline number was real, the arithmetic was correct, nobody lied, and the model still fell apart on live data. The cause is almost never fraud. It is that the number was computed on data that had, through one path or another, already influenced the model. You will learn the four paths, the protocol that closes them, and why the demo you are shown next quarter is best understood as training-set performance.

The divergence

Overfitting is not a synonym for a bad model. It names a specific event with a specific time signature: the moment training continues to improve performance on data the model has seen while performance on data it has not seen starts getting worse. Before that moment, more training helps. After it, more training actively hurts — the model is spending its remaining capacity on the noise in the training set, and noise does not repeat.

The structural problem is that the training curve alone cannot show you this. From inside training, everything looks like progress: the loss goes down every epoch, monotonically, right through the point where the model started harming itself. The only way to see the divergence is to hold data back and measure on it as you go.

Training loss and validation loss plotted against training epochs: training loss falls continuously while validation loss falls, bottoms out, and then rises, marking the onset of memorizationtraining epochsloss (lower is better)divergence pointmemorization: seen data improves,unseen data degradesearly stop heretraining lossvalidation lossboth falling:real structure found
Figure 2.1 — Where learning stops and memorizing begins. Training loss (blue) falls for as long as you let it. Validation loss (garnet) tracks it while the model is finding real structure, bottoms out at the divergence point, and then rises as the model fits noise that does not recur in unseen data. The shaded region is pure memorization: every additional epoch there makes the deployed model worse while the training metric keeps improving. Early stopping means keeping the weights from the marked minimum, not the ones from the end of the run.

Three consequences follow. First, early stopping — keeping the checkpoint at the validation minimum rather than the final one — is not a trick; it is the direct operational reading of this curve. Second, a team that reports only training loss has not withheld the interesting number, they have failed to compute it. Third, and most usefully for you: if someone shows you a single loss curve going down and calls it evidence of learning, the correct question is simply "what is the other curve doing."

Leakage: how the test set gets contaminated

Data leakage is any path by which information from the evaluation data reaches the model — directly, through a feature, or through the humans tuning it. Leakage does not produce error messages. It produces excellent numbers, which is what makes it the most dangerous failure mode in applied ML: the symptom of leakage is success.

There are four paths, and they are worth memorizing as a set because each has a different remedy.

PathWhat happensSymptomRemedy
DuplicationThe same or near-same records appear in both train and test — common with scraped corpora, resubmitted documents, and templated text.Test performance far above validation performance, or suspiciously uniform accuracy across difficulty levels.Deduplicate before splitting, including near-duplicates (hashing, then similarity screening).
Feature leakageA feature encodes the answer because it is only populated after the outcome is known.One feature dominates importance rankings; performance collapses in production where that feature is empty.For each feature, ask when it becomes available relative to prediction time; drop anything not available at inference.
Temporal leakageA random split puts future records in training and past records in test, letting the model learn from events that had not happened yet.Excellent offline metrics on any time-dependent problem; steady degradation in live use.Split chronologically: train on everything before date T, test on everything after.
Human leakageThe team evaluates on the test set repeatedly and selects models, features, and thresholds based on those results.The test number creeps up over the project's life in small increments; no single decision looks wrong.Separate validation from test; touch the test set once, at the end, with the decision already made.
Worked example — the feature that knew the answer

A compliance team builds a detector that flags internal communications warranting review. It reports 0.94 precision offline. In production, precision is 0.31 and nobody can reproduce the offline result.

The cause: one of the 60 input features was reviewer_queue_id, populated by the case management system. In the historical export used for training, that field was non-null for every document that had actually been escalated — because escalation is what puts a document in a reviewer queue. The model learned, correctly and uselessly, that documents with a queue id are violations. At prediction time the field is always null, because the whole point of the model is to decide whether a document should enter a queue. The feature encoded the outcome, and it encoded it perfectly.

The tell was visible before launch and was missed: a single feature carried nearly all of the model's importance weight, and the offline number was better than the human reviewers' own agreement rate. Both are leakage signatures.

The one that gets everyone

Human leakage is the hardest to see because no individual step is improper. You evaluate, you learn something, you improve the model, you evaluate again. Forty iterations later the held-out set has been used to make forty decisions, and it is no longer held out in any meaningful sense — it has become a very expensive validation set, and your reported number is the maximum of forty noisy draws rather than an unbiased estimate. The remedy is procedural, not technical: a validation set you may abuse freely, and a test set with an access policy.

The holdout as chain of custody

The three-way split is standard: the training set fits the parameters, the validation set guides every human and automated decision (architecture, features, hyperparameters, early stopping, thresholds), and the holdout or test set is measured once, at the end, to produce an honest estimate of performance on unseen data. Typical proportions are 70/15/15, but proportions matter far less than the discipline governing the third partition.

The useful frame is evidentiary. The test set is admissible only for as long as its chain of custody is intact. Every time a decision is made in light of test results, the sample has been contaminated by the process it was meant to evaluate — and unlike physical evidence, the contamination leaves no mark. The number still prints. This is why serious teams write the policy down: who may run the test evaluation, how many times, and what happens when the result is disappointing (the answer is not "iterate against it").

Data-split chain of custody: a dataset deduplicated and split chronologically into train, validation, and test, with dashed danger arrows showing the four leakage paths that puncture the boundariesRaw datasetdedupe firstSplit by datebefore any tuningTrain (70%)fits parameterstouched: constantlyValidation (15%)guides every decisiontouched: freelyTest / holdout (15%)sealed until finaltouched: once1. duplication — same records land in both partitions4. human leakagerepeated peeking2. feature leakage3. random split = temporal leak
Figure 2.2 — Chain of custody, and the four ways it breaks. Deduplicate, then split by date before any modeling decision is made. Train fits parameters; validation absorbs every experiment; the holdout stays sealed and is opened once. The dashed arrows are the four leakage paths: duplicate records crossing the partition wall, a feature carrying the outcome backward into training, a random split shuffling future into past, and the team itself carrying information out of the holdout by repeated evaluation.
Cross-reference

Guide Nº 03 (Evals) builds this discipline at the application layer: held-out task suites, versioned graders, and the rule that a suite you tune against stops being an eval. This module is the same epistemology one layer down, at the model itself. The rules rhyme because the underlying problem is identical — you cannot measure a system with an instrument the system has already been fitted to.

Why demos are always overfit

A product demo is a curated performance on selected inputs, prepared by people who know which inputs fail. That is not an accusation; it is what a demo is. The queries were chosen because they work, the documents were chosen because the model handles them, and any example that embarrassed the system during rehearsal was removed. In the vocabulary of this module: a demo reports training-set performance, whatever data it happens to run on.

This means the appropriate response to an impressive demo is neither belief nor cynicism. Both are unpriced. The appropriate response is a distribution request, and it has a standard form: run this on a sample I select, from my data, with my labels, and let me see the failures. A vendor who can do this within a week has a real product. A vendor who cannot has told you something more informative than the demo did.

Anti-pattern: the demo-to-production leap

Symptom: a purchase decision, roadmap commitment, or go-live date justified by demo performance, with no measurement on the buyer's own distribution. Mechanism: demo inputs are selected by the party being evaluated, which is exactly the structure of a training set. Corrective: a pilot on a buyer-selected sample with the metric, the labeling procedure, and the acceptance threshold agreed in writing before results exist. Module 7 specifies the terms.

The same discipline applies internally, and this is where product managers most often lose the thread. Your own team's demo to the executive review is subject to identical selection pressure — the engineer chose the five examples that morning, and chose them by running twenty. Ask for the twenty.

Module 03 Embeddings: the workhorse primitive

If you learn one mechanism from this course that changes how you read product roadmaps, it is this one. An embedding is a learned map from discrete things — words, documents, products, users, images — into a space of numbers where geometric closeness stands in for relatedness. Once your catalog lives in that space, an enormous share of what looks like distinct machine learning products collapses into a single operation: find the nearest points.

The practical payoff is estimation speed. A colleague asks for semantic search over support tickets, then for a related-articles rail, then for automatic topic clusters, then for a triage classifier. That is not four projects. It is one index and four query patterns, and knowing that lets you price the request accurately in an afternoon. The corresponding hazard is equally sharp: embeddings encode only the notion of similarity their training objective rewarded, they respect no hard constraints, and swapping the model invalidates every vector you have stored.

From symbols to geometry

Computers cannot compare meanings; they compare numbers. An embedding model is a neural network trained so that the vector it produces for an input sits near the vectors of related inputs. The output is typically a few hundred to a few thousand floating-point numbers — 768, 1,536, and 3,072 dimensions are common — and no individual dimension has a human-readable meaning. The information lives in the relative positions.

The crucial question is: near in what sense? The answer is never "in the sense of meaning." It is always "in whatever sense the training objective rewarded." A model trained by pulling together text fragments that appeared close together in documents learns topical adjacency. A model trained on question-and-answer pairs learns that a question should sit near its answer — which are topically related but textually dissimilar. A model trained on product co-purchase data learns that a corkscrew is near a wine rack, which no text model would say.

The load-bearing idea

An embedding space has no innate notion of similarity. It has exactly the notion its training objective installed. Every surprising retrieval result — the two documents your users think are unrelated but the model calls a 0.91 match — is that objective showing through, and the diagnosis starts with "what was this model trained to pull together," not "why is the model wrong."

This is why the choice of embedding model is a product decision with a testable criterion. For the wine cellar, a general-purpose text model trained on web documents will place a Chablis tasting note near a Sancerre note because they share vocabulary — mineral, citrus, saline. That happens to be useful. It will also place a note describing a wine's flaws near a note praising the same characteristics, because both mention brett and barnyard, and it has no encoding of valence. That is not useful, and you will only discover it by testing the model against pairs you have labeled yourself.

Similarity: the metrics and what they assume

Given two vectors, three measures dominate practice, and they answer different questions.

MetricWhat it measuresAssumesTypical use
Cosine similarityThe angle between vectors; magnitude ignored. Range −1 to 1.Direction carries the meaning; length is noise (e.g. document length).Text retrieval, the default for most embedding APIs.
Dot productAngle and magnitude together.Magnitude carries signal — popularity, confidence, frequency.Recommenders where item popularity should tilt results.
Euclidean (L2)Straight-line distance between points.Absolute position matters, not just direction.Clustering, anomaly detection, low-dimensional spaces.

The relationship worth internalizing: on vectors that have been normalized to unit length, cosine similarity and Euclidean distance rank neighbors identically, and dot product becomes cosine. Normalization is therefore the decision that collapses the choice, and most embedding providers normalize for you — which is why cosine is the default and why the metric debate is usually less consequential than teams expect.

What no metric can do is repair a mismatch between the model's notion of similar and your product's. If your users mean "same wine style at a lower price" and the model means "similar tasting vocabulary," switching from cosine to dot product changes nothing that matters. The fix is a different model, a fine-tuned one, or a hybrid with structured filters.

Anti-pattern: the universal threshold

Symptom: a rule like "cosine ≥ 0.8 means a match" written into product logic, carried between projects, or quoted in a spec. Mechanism: similarity scores are not calibrated probabilities — their distribution depends on the model, the corpus, and the text length, so 0.8 can be near-identical in one space and barely related in another. Some models place nearly all real text pairs above 0.7 simply because of how their vectors are distributed. Corrective: label a few hundred pairs from your own corpus, plot the score distribution for matches and non-matches, and choose the threshold that hits your precision/recall target — then re-derive it every time the model changes.

Four products, one primitive

Here is the collapse. Every one of these features is nearest-neighbor lookup in an embedding space, differing only in what plays the role of query and what you do with the neighbors.

  • Semantic search — query: the user's text, embedded. Neighbors: documents. Output: the neighbors, ranked.
  • Recommendation — query: an item the user liked, or the average of several. Neighbors: catalog items. Output: neighbors minus what they have already seen.
  • Clustering — query: none; instead find groups of points that are mutually near. Output: group assignments.
  • Classification — query: the new item. Neighbors: labeled examples. Output: the majority label among the k nearest — a working classifier with no training step at all.

That last one deserves emphasis because it is the most under-used tool in an early-stage product. If you have 200 labeled support tickets and need routing today, embedding them and assigning each new ticket the majority label of its 15 nearest neighbors will often get you to 70–80% accuracy in an afternoon, with the enormous operational advantage that adding a new category means adding examples rather than retraining anything.

Four product surfaces — search, recommendation, clustering, classification — arranged around a single nearest-neighbor core, each annotated with what plays the role of query and neighborsNearest neighborsin embedding spaceSemantic searchquery = user textneighbors = documentsRecommendationquery = liked item(s)neighbors = catalog, minus seenClusteringquery = noneneighbors = each otherClassification (k-NN)query = new itemneighbors = labeled examplesone index, four query patterns
Figure 3.1 — Four costumes, one operation. Search, recommendation, clustering, and classification are the same nearest-neighbor lookup; only the query and the post-processing differ. Search embeds the user's text; recommendation uses an item the user liked; clustering has no external query and groups points by mutual proximity; k-NN classification takes the majority label among the nearest labeled examples. The engineering cost of the second, third, and fourth feature is far below the first, because the index is already built.

The wine cellar, embedded

Make it concrete. Take 1,800 wines, each with a tasting note of 40–80 words. Embed every note; store the 1,800 vectors. Now a member says: something like the Chablis I loved, but I want to try something new. Embed that Chablis's note, find its nearest neighbors, drop what the member has already bought, return the top six.

What this does spectacularly well is the long-tail semantic match that keyword search cannot reach. The member's Chablis note says "oyster-shell minerality, taut, unoaked." A Muscadet from a producer whose note reads "saline, chiseled, no oak influence" shares almost no vocabulary with it and sits three positions away in the embedding space. No keyword system finds that. That single capability is the reason embeddings are in the product.

A two-dimensional projection of wine tasting-note embeddings showing three labeled neighborhoods, a query point with its nearest-neighbor radius, a drawn cluster boundary, and a structurally similar but over-budget bottle inside the radiusprojected dimension 1 (no intrinsic meaning)projected dimension 2austere old-world redstropical, oaked whitesk = 5 nearest-neighbor radiusquery: Chablis 2019Muscadet · $24Aligoté · $31Picpoul · $19Grand Cru · $310geometrically near,over the $50 ceilingclusters are geometry:the labels above werewritten by a human,not discovered
Figure 3.2 — The cellar as geometry. Each dot is one wine's tasting note embedded and projected to two dimensions for display; the axes have no intrinsic meaning and the neighborhoods (dashed) are regions a human read and named after the fact. The query bottle sits at the garnet point, and its five nearest neighbors are the candidate recommendations — including a Muscadet that shares almost no vocabulary with the query note, which is exactly the match keyword search misses. The red neighbor shows the limit: a $310 Grand Cru is geometrically among the nearest because style, not price, is what the space encodes. Hard constraints must be enforced outside the geometry.

And there is the faceplant. The member's request was "under $50, 2015 or later, and not something I've already bought." None of those constraints exist in the embedding space. Price is not a direction you can travel; vintage is not a region. A tasting note that says "an astonishing value" will pull a $310 bottle toward the cheap neighborhood, because the space encodes the language, not the fact.

When it misleads

Similarity is a soft, continuous, uncalibrated signal. Hard constraints — price ceilings, date ranges, entitlements, jurisdictional restrictions, allergen exclusions — are boolean facts about records. Never encode a boolean fact as a soft preference in a vector and hope the ranking respects it; it will violate the constraint the first time a strong stylistic match sits just outside the rule, and the violation will look like a good recommendation to everyone except the customer.

The correct architecture is the hybrid: apply structured filters first (a SQL WHERE clause, or the metadata filter your vector database provides), then rank the survivors by similarity. Filter for correctness, rank for relevance. Getting this order right is most of what separates a vector-search feature that ships from one that gets pulled.

Operational reality: indexes, drift, migrations

Comparing a query against 1,800 vectors is trivial arithmetic. Comparing it against 40 million is not, and this is where embeddings become infrastructure. An ANN index — approximate nearest neighbor, in structures like HNSW or IVF — makes the query fast by giving up the guarantee that it returns the true nearest neighbors. Typical settings recall 95–99% of true neighbors at a fraction of the cost, and the tunable knob trades recall against latency and memory.

That approximation is usually fine and occasionally is not, and the distinction is worth stating in a spec. For discovery surfaces, missing one of the ten best matches is invisible. For a compliance screen where the whole point is that nothing similar to a known-bad document escapes, a 97% recall index has a defined miss rate, and you should either raise the recall setting or run an exact scan over the filtered candidate set. Approximation is a product decision.

Anti-pattern: the silent re-embedding

Symptom: a routine upgrade to a newer embedding model, applied to the query path, while the stored vectors were produced by the old model. Search quality degrades to something between mediocre and random, and no error is raised anywhere. Mechanism: two embedding models produce coordinates in unrelated spaces. Comparing a vector from model B against an index built with model A is comparing coordinates from different maps — the arithmetic still returns a number, and the number is meaningless. Corrective: treat the embedding model as a versioned schema. Re-embed the entire corpus into a new index, run both indexes in parallel while comparing retrieval quality on a fixed query set, then cut over and retire the old one. Budget the re-embedding cost and time before you promise the upgrade.

Two more obligations round out the operational picture. First, corpora grow and shift, so the neighborhoods that made sense at launch drift; a scheduled retrieval-quality check on a fixed labeled query set is the monitoring that catches it. Second, storage is real: 40 million documents at 1,536 dimensions in 4-byte floats is about 245 GB of raw vectors before index overhead, which is a hosting decision, not a rounding error — and it is a large part of why dimensionality-reduced embedding variants exist.

Module 04 The classical toolkit — and the showdown

The most expensive misconception in applied machine learning is that model families form a quality ladder with deep learning at the top. They do not. They are instruments matched to data types, and on the data type that dominates business — rows and columns, with heterogeneous features, a few thousand to a few million records, and no useful pretraining to borrow — an ensemble of small decision trees usually wins outright against a neural network, at a hundredth of the cost and a tenth of the development time.

This module teaches the two classical families a product manager must be able to argue for, the decision procedure that routes a problem to the right family, and then the promised showdown: the wine-recommendation problem solved three ways — embeddings, gradient-boosted trees, and an LLM with retrieval — with assumptions declared and the winner not rigged. The conclusion is more interesting than any single victory, and it is the sort of conclusion that only appears when you compare honestly.

Linear models: the interrogable baseline

A linear regression predicts by multiplying each input by a learned weight and adding the results. Its virtue is not accuracy; it is that the weights are readable claims. Fit willingness-to-pay against wine features and you get statements a human can accept or dispute:

willingness_to_pay = 11.4*(critic_score - 88) + 6.2*(years_in_bottle) - 0.9*(alcohol_pct) + 34.10

That first coefficient says each point of critic score above 88 adds about $11.40 to what this member segment will pay. A buyer can check it against what they know about the market and either nod or object — and either reaction is more informative than an accuracy metric. Logistic regression is the same instrument for classification, returning well-calibrated probabilities rather than a score, which matters whenever a downstream decision needs a threshold with an expected-cost calculation behind it.

The reason to insist on a linear model even when you intend to ship something else is the baseline. A number without a baseline is unpriced: 0.87 AUC is excellent for some problems and embarrassing for others, and the only way to know which is to see what a simple model gets. Three baselines are worth requesting by name — predict the majority class or the mean, predict the most popular items, and a logistic or linear regression on the obvious features.

The load-bearing idea

A baseline you cannot beat is a finding, not an embarrassment. If a regression on six features matches your neural network, you have learned that the problem's signal is mostly linear and the sophisticated model is buying you operational cost rather than accuracy. Ship the regression, redirect the team, and report it as the result it is.

From your other life

A linear model deposes well. Every coefficient is an answerable question — why does alcohol percentage carry a negative weight, and would that survive on a different segment? Complex models can be interrogated too, with tools like feature attributions, but their answers are reconstructions rather than the mechanism itself. When a decision must be explained to a regulator, a customer, or a court, the model whose reasoning is its parameters starts several steps ahead.

Trees and GBMs: why they win on tables

A decision tree splits the data on one feature at a time — critic_score < 90?, then price < 45? — carving feature space into rectangular regions and predicting a constant within each. A single tree is weak and unstable. The insight that makes it powerful is boosting: fit a small tree, look at what it got wrong, fit the next small tree to those residual errors, add it to the ensemble, and repeat several hundred times. Each tree is a shallow correction; the sum is a precise, highly nonlinear function. That is a gradient-boosted tree ensemble — XGBoost, LightGBM, CatBoost — and it is the same gradient-descent idea from module 1, taking steps in function space instead of weight space.

A decision tree partitioning a two-dimensional wine feature space of price against critic score, and a sequence of three boosted trees each fitting the previous ensemble's remaining errorsOne tree: axis-aligned splitsrating 88rating 84rating 93rating 90price →critic score →splits are thresholds; each regionpredicts one constantBoosting: each tree fits what remainsTree 1bulk signalTree 2tree 1's errorsTree 3what's left++Ensemble prediction = sum of 300–900 shallow treesResidual error shrinks with each round; the learning ratecontrols how much of each tree is added, and early stoppingon validation loss picks the tree count.
Figure 4.1 — Trees, then boosting. Left: a single tree carves the price × critic-score plane into rectangles with threshold splits and predicts one constant per region — which is why trees handle features on wildly different scales without normalization. Right: boosting fits tree 1 to the data, tree 2 to tree 1's leftover errors, tree 3 to what still remains, and sums a few hundred such corrections. It is gradient descent again, taking steps in function space, with early stopping on validation loss deciding how many trees to keep.

Why does this beat deep learning on tables? Four reasons, all stateable in a meeting.

  • Feature heterogeneity. Business tables mix dollars, counts, dates, and categories with hundreds of levels. Trees split on thresholds and are indifferent to scale; neural networks need every feature normalized and encoded, and remain sensitive to how you did it.
  • Sample size. Business problems live at thousands to low millions of rows. Neural networks show their advantage in the regime where data is effectively unlimited relative to the pattern's complexity.
  • No useful pretraining. Deep learning's dominance in text and images comes from transferring representations learned on enormous general corpora. There is no pretrained model for your subscription table's idiosyncratic columns.
  • Irregular structure. Tabular relationships are full of thresholds and interactions — a discount matters below a price point and not above it — which is precisely what tree splits represent naturally and smooth networks approximate awkwardly.
Anti-pattern: neural nets on small tabular data

Symptom: a proposal to build a deep network for a few thousand rows of structured data, usually justified by the architecture's sophistication rather than by a measured comparison. Mechanism: all four advantages of deep learning are absent at that scale, while its costs — tuning burden, compute, opacity, brittleness to feature encoding — are fully present. Corrective: a linear baseline and a gradient-boosted ensemble, both in the first week, with the deep model admitted only if it beats them on a held-out set by a margin worth its operational cost.

The honest default

The routing procedure is short enough to hold in your head, and its most important property is not the branches but the asymmetry it imposes: the burden of proof sits on the more expensive model, always.

Decision flowchart routing a problem by data type to a model family: tabular data to a gradient-boosted ensemble after a linear baseline, perception data to neural networks, open-ended language to an LLM, with cost and burden of proof increasing left to rightWhat is the input?Rows and columns (tabular)Images, audio, free textOpen-ended language behaviorLinear / logistic baseline firstGradient-boosted treesthe honest defaultNeural networkpretrained where possibleLLM, with retrievalgeneration, not rankingcost, latency, and burden of proof increase → each escalation must beat the cheaper model on held-out data
Figure 4.2 — Routing a problem, with the burden of proof marked. Tabular inputs go to a gradient-boosted ensemble after a linear baseline — the marked default, because that is where most business data lives. Perception inputs (images, audio, raw text) go to neural networks, preferably pretrained. Open-ended language behavior goes to an LLM with retrieval. The gold axis is the point: moving right costs more in money, latency, and opacity, so every escalation carries the burden of beating the cheaper option on a held-out set by a margin worth that cost.

Two clarifications keep the flowchart honest. First, most real problems are mixed — the wine recommender has structured purchase history and free-text tasting notes — and the right answer is usually to convert the unstructured part into features (embeddings compressed to a handful of dimensions, or model-derived scores) and feed them to the tabular model. Second, the flowchart routes the ranking or prediction task. It says nothing about the presentation layer, which is where LLMs earn their keep.

The showdown: wine recommendation three ways

Now the comparison the module promised. The task: given a member, rank the current 1,800-bottle allocation and pick six. Three approaches, one problem, assumptions on the table first — because a comparison whose assumptions are hidden is a marketing exercise.

Declared assumptions

Roughly 10,000 labeled purchase-and-rating histories across 2,400 active members; structured features available per member and per SKU (purchase history, price band, region, grape, vintage, critic score, inventory); tasting-note text available for every SKU; offline ranking quality measured as NDCG@6 against held-out subsequent purchases with ratings, on a chronological split; cost quoted per 1,000 generated recommendation sets at 2026 commodity prices; latency measured at p50 for a single member's ranking. A popularity baseline scores 0.22. Everything below moves if these assumptions move — particularly the 10,000 labeled histories, which is the number that makes the supervised approach viable at all.

ApproachCost / 1K setsp50 latencyNDCG@6 (established members)NDCG@6 (cold start, <5 ratings)
Popularity baseline≈ $0.002 ms0.220.21
Embeddings + k-NN on tasting notes$0.1240 ms0.310.29
GBM on structured features$0.0312 ms0.440.19
LLM with retrieval$9.402,300 ms0.360.31
Three panels comparing embeddings, gradient-boosted trees, and an LLM with retrieval on cost per thousand recommendation sets, median latency, and offline ranking qualityCost / 1,000 sets$0.12$0.03$9.40embGBMLLMp50 latency40 ms12 ms2,300 msembGBMLLMNDCG@6, established members0.310.440.36popularity baseline 0.22embGBMLLMAssumptions: ~10,000 labeled purchase histories, 2,400 members, 1,800 SKUs, structured features andtasting notes available; chronological split; cold-start results differ sharply and are given in the table.
Figure 4.3 — Three approaches, three axes. The GBM is cheapest, fastest, and best on ranking quality for members with purchase history — 0.44 NDCG@6 against a 0.22 popularity baseline. The LLM costs roughly 300× more per recommendation set and is about 190× slower while ranking worse than the GBM. Embeddings sit in the middle on quality and hold up where the GBM collapses: for members with fewer than five ratings, the GBM falls to 0.19 (below the popularity baseline) while embeddings hold 0.29. The panels use independent scales; assumptions are stated because the comparison is worthless without them.

Read the numbers before drawing the conclusion. The GBM wins ranking quality per dollar decisively where labeled history exists — it is 300 times cheaper than the LLM and ranks better. The LLM ranks worse than the cheap model while costing dramatically more, which is the result most teams do not expect and the reason this comparison is worth running rather than assuming. Embeddings are mid-quality and mid-cost, but they are the only approach that does not depend on the member having a history, which is why they hold up in cold start where the GBM drops below the popularity baseline.

The load-bearing idea

The question "which model is best for recommendations" was malformed. Performance is regime-dependent: the GBM owns established members, embeddings own cold start and long-tail discovery, and the LLM owns neither ranking regime — it owns the conversational surface and the explanation. The honest first build is a GBM whose feature set includes embedding-derived similarity scores, with the LLM as a presentation layer that explains the ranking rather than producing it.

That architecture is worth stating explicitly because it is what the evidence supports and it is not what either enthusiasm or skepticism would have produced. The ranker is a boosted ensemble over structured features plus a handful of embedding-derived columns (similarity to the member's three highest-rated bottles, distance to their purchase centroid). Cold-start members are routed to pure similarity until they have five ratings. The LLM takes the ranked six and writes the note that says why this Muscadet, given that Chablis — the part of the product members actually quote back, and a job the cheap models cannot do at all. Each component does the thing it is best at, and the expensive component is used where its cost buys something the cheap ones cannot deliver.

Module 05 Fine-tuning demystified

"We'll fine-tune it" is the most confidently misused phrase in AI product planning. It is spoken as though it meant "teach the model our business," and it does not. Fine-tuning is continued gradient descent — the identical mechanism from module 1 — run on a smaller, narrower dataset starting from an already-trained model's weights. It moves numbers. It does not install a knowledge base.

That distinction predicts almost everything you need to know about when fine-tuning works. It reliably changes behavior: format, tone, task framing, refusal patterns, how the model structures an answer. It changes knowledge unreliably and expensively, because facts distributed across billions of weights are a terrible database — you cannot update one, you cannot audit one, and you cannot cite one. This module gives you the three flavors of tuning, what each costs, and the triage question that decides whether you need any of them.

What fine-tuning actually changes

Start from where a base model comes from. Pretraining ran gradient descent over an enormous general corpus, producing weights that encode broad linguistic and world structure. Fine-tuning resumes that same process, at a much smaller learning rate, on a curated dataset of your examples. The weights shift a little. The architecture does not change; no new storage is added; nothing is indexed.

Consider what it takes to make a model reliably reproduce a fact — say, that a particular regulation's compliance deadline moved to March 2027. To install that through weight updates you would need enough examples, repeated enough times, at a large enough learning rate, that the update survives all the competing pressure from every other example. Do too little and the model produces the old answer or an interpolation between the two. Do enough to be reliable and you have moved the weights hard enough to degrade neighboring capabilities. Meanwhile the fact will change again next quarter, and the only remedy is another training run.

Now consider making the model always answer in your firm's memo structure — issue, rule, application, conclusion, with citations in a house format. Two hundred well-constructed examples will do it, and the change is stable because it is a consistent pattern rather than a point fact competing against a mountain of prior evidence.

The load-bearing idea

Weights are a lossy, unauditable, expensive-to-update store of facts and a good store of patterns. So fine-tuning is the right instrument for how the model behaves and the wrong instrument for what the model knows. When someone proposes tuning to fix a knowledge gap, they have chosen a database with no update statement, no audit log, and no citation mechanism.

Full fine-tune versus LoRA

A full fine-tune updates every parameter. For a 7-billion-parameter model that means holding the weights, their gradients, and the optimizer's per-parameter state in memory simultaneously — in practice several times the model's own size, which is why full tuning of even mid-sized models means multi-GPU infrastructure. You also get a complete new model artifact per tuned variant: three customer-specific tunes means three full model copies to store, serve, and version.

LoRA — low-rank adaptation — takes a different route. Freeze the base model entirely. Alongside selected weight matrices, train small pairs of matrices whose product has the same shape as the original, and add that product to the frozen weight at inference. Because those matrices are deliberately low-rank (an inner dimension of 8 to 64 is typical), the trainable parameter count lands around 0.1–1% of the model's. The base model never moves; the adapter is a file of tens to hundreds of megabytes.

The operational consequences are larger than the cost savings. Adapters are swappable — one base model in memory, many adapters loaded per request, which turns per-customer tuning from an infrastructure program into a file management problem. And because the base weights are untouched, the blast radius of a bad tune is bounded: you unload the adapter.

Three panels showing which weights move under full fine-tuning, LoRA, and preference optimization, annotated with trainable parameter counts and order-of-magnitude cost per runFull fine-tuneevery layer movestrainable: 7,000M (100%)cost: $1,000s per runartifact: full model copyuse when: new domain, newmodality, very large dataLoRA adaptersbase frozentrainable: ~30M (0.4%)cost: $10s per runartifact: 100 MB adapter, swappableuse when: tone, format, taskframing — most real casesPreference optimizationoutput preferences reshapeddata: comparison pairscost: $100s–$1,000s per runartifact: full model or adapteruse when: judgment calls wherebetter is easier to rank than write
Figure 5.1 — Which weights move. Full fine-tuning updates every layer (garnet), producing a complete new model at four figures per run. LoRA freezes the base (cream) and trains small adapter matrices attached alongside each layer — roughly 0.4% of the parameters, tens of dollars per run, and a swappable file rather than a model copy. Preference optimization leaves capability intact and reshapes which of the model's existing outputs it favors, trained on ranked comparison pairs rather than demonstrations. Costs are order-of-magnitude for a 7B-class model in 2026 and move with hardware, not with the structure of the picture.
On the choice

The received wisdom that LoRA is the budget compromise is mostly wrong for the tasks companies actually attempt. For behavior shaping — output format, domain register, task framing — LoRA typically lands close enough to a full tune that the difference does not survive a blind evaluation. Full tuning earns its cost in narrower circumstances: adapting to a genuinely different domain distribution (a new language, a specialized notation), teaching a new modality, or training on data at a scale where the adapter's limited capacity becomes the binding constraint. Those cases are identifiable in advance — which means the default should be LoRA, with full tuning as the escalation that carries the burden of proof.

Preference optimization

The third family answers a different question. Supervised fine-tuning needs demonstrations: here is an input, here is the correct output, imitate it. But for many judgments — which of two summaries is more useful, which refusal is better calibrated, which explanation a member would find helpful — nobody can write the ideal output on demand, while anyone competent can rank two candidates in seconds.

Preference optimization trains on exactly that signal. Collect pairs where a human (or a model standing in for one) marked one response better, then adjust the model so preferred responses become more probable and rejected ones less so. RLHF does this through an intermediate reward model; DPO does it directly from the pairs, which is simpler and now more common in practice.

The critical property: preference optimization selects among behaviors the model can already produce. It shifts probability mass toward outputs already in the model's repertoire. If the model cannot write valid Terraform, no volume of preference data teaching it to prefer valid Terraform will make it able to — you would be rewarding a capability that is not there. Preference tuning is a taste transplant, not a skill transplant.

Worked example — where each flavor belongs

A contract-drafting assistant has three complaints against it. (1) It sometimes cites a superseded version of a regulation. (2) Its clause explanations are structurally inconsistent — sometimes a paragraph, sometimes a table, sometimes bullets. (3) When a clause is genuinely ambiguous, it picks an interpretation confidently instead of flagging the ambiguity, and reviewers consistently prefer the flagging version when shown both.

Three different instruments. (1) is a knowledge gap and belongs to retrieval over a versioned regulation store — tuning it in produces an unauditable citation that will be wrong again next quarter. (2) is a behavior gap with a writable correct output, so supervised LoRA on 200 well-structured examples. (3) is a judgment gap where reviewers can rank but struggle to specify: preference optimization on the comparison pairs the review process already generates. Sending all three to "fine-tune it" would fix one, waste money on another, and quietly corrupt the third.

The RAG question comes first

Before any of the three, run the triage. It has one question at the top, and getting it right saves more money than any other decision in this module: is the gap knowledge or behavior?

A knowledge gap means the model does not have the facts — your policies, your catalog, this quarter's regulations, the customer's account state. Retrieval fixes this properly: the facts live in a store you can update with a write, audit with a query, cite in the output, and permission per user. Tuning fixes it improperly, if at all.

A behavior gap means the model has whatever facts it needs but does the wrong thing with them — wrong format, wrong register, wrong task framing, wrong sense of when to hedge. Prompting fixes a surprising amount of this. Tuning fixes what prompting cannot, and buys back the context-window cost of a very long instruction block.

Triage flowchart classifying a model gap as knowledge or behavior and routing it through prompt engineering, retrieval, LoRA, or full fine-tuning with escalation criteria on each edgeObserved gapknowledge or behavior?missing / stale factswrong form or judgmentRetrieval (RAG)updatable · auditable · citableStill wrong? The gap wasretrieval quality, not the model.Prompt engineeringfree, instant, reversible — try firstinsufficient after real effortLoRA (or preference tuning)demonstrations vs. ranked pairsnew domain, modality, or huge dataFull fine-tuneburden of proof sits hereFresh facts never route to tuningweights have no update statement
Figure 5.2 — Triage before you tune. Classify the gap first. Missing or stale facts route hard left to retrieval, where the store can be written to, audited, and cited — and if the answer is still wrong afterward, the defect is retrieval quality rather than the model. Wrong form or judgment routes right: prompt engineering first because it is free and reversible, then LoRA (demonstrations) or preference tuning (ranked pairs), with a full fine-tune reserved for a new domain, a new modality, or data large enough to saturate an adapter. Nothing about fresh facts ever routes to tuning.
Cross-reference

Guide Nº 02 covers the retrieval side of this fork in depth — chunking, hybrid retrieval, grounding, and citation. The relevant handoff is simply this: retrieval and tuning are not competitors on a quality ladder. They address different defects, and a system with both usually has each doing its own job. The failure is using one for the other's problem.

Anti-pattern: fine-tuning as a reflex

Symptom: a tuning project proposed before anyone has seriously attempted prompting or retrieval, usually described as "teaching the model our domain," with no stated classification of the gap. Mechanism: tuning feels like the more serious intervention, so it attracts teams who want to be doing real machine learning. Corrective: require a written gap classification and evidence that the cheaper interventions were tried and measured, before any tuning budget is approved. In practice a large share of proposed tuning projects turn out to be retrieval problems or prompt problems, and the failed ones are disproportionately the knowledge cases.

Costs, data, and failure modes

Three practical matters decide whether a tuning project succeeds, and none of them is the choice of algorithm.

Data quality dominates volume. For behavior shaping, several hundred carefully constructed examples routinely outperform tens of thousands of scraped ones. The reason follows from module 1: the model fits whatever regularity is in the data, so inconsistency in your examples is a regularity it learns — teach it that the format varies and it will faithfully vary the format. The expensive part of a tuning project is producing 300 examples that genuinely agree with each other, and that cost is measured in expert hours, not GPU hours.

Catastrophic forgetting is the silent regression. Aggressive tuning on a narrow objective degrades capabilities outside it. A model tuned hard on clause drafting gets worse at summarizing, at following unrelated instructions, at declining out-of-scope requests. Nothing announces this — the tuned task looks better, which is what everyone is looking at. It is caught only by evaluating capabilities you did not tune for, which nobody does unless the eval plan requires it.

The before/after evaluation is not optional. Every tuning run needs: a held-out set for the target behavior, a regression set covering general capability, and a fixed decision rule stated in advance. "It looks better" is the standard failure, and it fails in the specific way module 2 predicts — the examples someone looks at are the ones they remember struggling with, which is a training set.

Reading a vendor's tuning claim

"Our model is fine-tuned for financial services compliance" can mean four very different things, and the question that separates them is what moved? (1) Nothing moved — it is a system prompt with domain instructions, which is fine but is not tuning and should not be priced as a moat. (2) A LoRA adapter on a base model, trained on their example set: real, modest, and the useful follow-up is how many examples and who wrote them. (3) A full fine-tune on a proprietary corpus: genuine investment, and now ask what is in the corpus and whether your evaluation data could be in it. (4) Preference tuning on expert-ranked outputs: often the most valuable of the four, because the rankings encode judgment that is hard to acquire. Then ask the module-2 question regardless: what does the before/after evaluation show, on what held-out set, against what base model?

Module 06 Making models smaller

Two questions decide whether a model can run where you want it to run: does it fit in the available memory, and is it fast enough. Both have arithmetic answers, and the arithmetic is simple enough to do in a meeting — which is useful, because "we'll self-host it" is frequently said by people who have not done it and would have stopped talking if they had.

This module covers the two levers that make models smaller: quantization, which stores each weight in fewer bits, and distillation, which trains a small model to imitate a large one. Both trade quality for resources. The essential discipline is that the trade is measurable — you run the evaluation from module 2 before and after and you get a number — so any conversation about compression that stays qualitative is a conversation that has not been had properly.

Quantization: fewer bits per weight

A model's weights are numbers, and numbers need bits. Training typically uses 16-bit floating point, so each parameter costs 2 bytes. Quantization stores them in fewer bits — 8-bit integers at 1 byte, 4-bit at half a byte — by mapping the range of real values onto a coarser grid of representable ones. The memory saving is not an optimization to be hoped for; it is arithmetic.

memory for weights = parameter_count x bytes_per_parameter

7B model:   FP16 -> 14.0 GB    INT8 -> 7.0 GB    INT4 -> 3.5 GB
70B model:  FP16 -> 140 GB     INT8 -> 70 GB     INT4 -> 35 GB

Add roughly 15–25% on top for the KV cache, activations, and runtime overhead, scaling with context length and batch size. So on a single 24 GB card: a 7B model runs comfortably at FP16 (about 17 GB all-in), a 13B model needs INT8, a 34B model needs INT4 and is tight, and a 70B model does not fit at any precision that preserves useful quality. That last sentence is the one that ends most self-hosting proposals, and it takes fifteen seconds to derive.

A single weight value shown on three number lines at FP16, INT8, and INT4 precision with progressively coarser representable buckets, beside a table of memory per model size at each precision and common GPU memory thresholdsOne weight, three precisionsFP160.4137INT80.41INT40.5Coarser buckets: the stored value drifts from the true one.Each weight's error is tiny; whether the accumulated errormatters is a question only your task evaluation answers.Weight memory (add 15–25% overhead)model FP16 INT8 INT47B 14.0 GB 7.0 GB 3.5 GB13B 26.0 GB 13.0 GB 6.5 GB34B 68.0 GB 34.0 GB 17.0 GB70B 140.0 GB 70.0 GB 35.0 GBFits on one card?16 GB: 7B INT8, 13B INT424 GB: 7B FP16, 13B INT8, 34B INT448 GB: 34B INT8, 70B INT4 (tight)70B FP16: needs multiple cardsLonger context and larger batches raise the overhead share.
Figure 6.1 — Precision, memory, and what fits. Left: the same weight stored at three precisions. FP16 offers fine-grained buckets and preserves 0.4137; INT8 rounds to 0.41; INT4 has so few buckets that it lands on 0.5. Each individual error is small, and whether the accumulated error matters is empirical. Right: weight memory is parameter count times bytes per parameter (2, 1, and 0.5 bytes), plus 15–25% for KV cache and activations. The fits-on-one-card lines are the arithmetic that settles most self-hosting debates before they start.

What is lost is precision at the margins. Rounding each weight introduces a small error, errors accumulate through the layers, and the model's outputs shift slightly. Modern quantization methods reduce this considerably by calibrating on sample data and keeping the most sensitive layers at higher precision — but they reduce the loss rather than eliminating it.

The size of the quality cost is task-dependent, and this is the part people get wrong in both directions. On tasks with substantial redundancy — classification, tagging, summarization, extraction — INT8 is frequently indistinguishable from FP16 and INT4 costs a point or two. On tasks where a long chain of steps must all be right — multi-step reasoning, precise code generation, exact arithmetic — small per-step degradations compound and the drop can be severe. There is no universal quantization penalty. There is only your task's number, and you get it by running your evaluation set twice.

Distillation: the student and the teacher

Distillation attacks size differently. Instead of compressing an existing model's weights, train a smaller model to reproduce a larger model's outputs — historically from scratch on the teacher's outputs, though for LLMs today the student is usually an already-pretrained base fine-tuned on them. The teacher generates outputs — often with its full probability distributions, which carry more information than the final answer alone — and the student learns to match them on that data.

What makes this work better than training the small model on the original labels is that the teacher's outputs are a richer signal. A ground-truth label says "this ticket is a billing issue." The teacher says "73% billing, 19% account access, 5% refund, 3% other," which encodes the similarity structure between categories, and the student learns from that structure.

The critical limitation is the boundary, and how sharp it is depends on how the student was built. The student learned to imitate the teacher on the distribution it was shown, and inside that region it can be remarkably close to the teacher at a fraction of the size. A student trained only to imitate on that slice has no fallback outside it — it never had the teacher's general capability, only an imitation of its behavior on a specific slice — so the degradation at the boundary is a cliff: not gradual, and it does not announce itself. When distillation instead fine-tunes an already-pretrained base (the common case for LLMs today), the student keeps that base's broad capability and degrades more gently past the taught slice. The narrow-slice case is the one to design around, because its failure is the one you cannot see coming.

Distillation flow showing a teacher model generating outputs on a taught distribution that become a student model's training targets, with the taught region bounded and the quality cliff outside it marked as a dashed danger zoneTeacher — 70Bgeneral capabilityOutputs on task datafull distributions, not just labelsStudent — 8Bimitates within the sliceoutside the taught distribution: an imitation-only student has no fallbacktaught distributionstudent ≈ teacher herenew phrasingnew categoryanother languageadversarial input
Figure 6.2 — The student's boundary. The teacher generates outputs on a slice of task data — ideally full probability distributions, which encode the similarity structure between categories rather than just the winning label — and the student trains to match them. Inside the taught distribution (green), an 8B student can approach a 70B teacher's quality. Outside it, a student trained only to imitate has no general capability to fall back on, and its failure is a cliff rather than a slope: unfamiliar phrasings, unseen categories, other languages, and adversarial inputs all land outside, with no signal that they have — whereas a student distilled onto an already-pretrained base degrades more gently.

The product consequence: a distilled model is a specialist you must fence. It belongs behind a router that sends anything unusual to the larger model, and behind a monitor that watches the input distribution for drift away from what it was taught — the same monitoring that module 8 requires for every deployed model, and more urgent here because a narrow-slice student's cliff is steeper.

Why this matters for self-hosting

Make it concrete on hardware you can touch. A single-GPU workstation with 24 GB of VRAM running a ROCm stack is a realistic home for a production-adjacent workload, and the arithmetic above tells you exactly what it will hold: a 7B model at FP16 with room for a long context, a 13B at INT8, a 34B at INT4 if you keep the context modest. Not a 70B, at any precision worth running.

Whether that constraint matters depends entirely on the task, which brings the module's final anti-pattern into view.

Anti-pattern: model size equals capability

Symptom: model selection made by parameter count or by a general leaderboard position, with sentences like "we need at least a 30B for this to be any good." Mechanism: parameter count is an input to capability, mediated by training data, tuning, and task fit — and a model distilled or tuned for your narrow task routinely beats a much larger generic one on that task while losing badly on everything else. Corrective: benchmark the candidates on your own held-out task set, at the precision you would actually deploy, and rank by that. The spec sheet is a prior, not a result.

The self-hosting decision itself is then a straightforward comparison, provided you count honestly. On the hosted side: per-token cost times projected volume. On the self-hosted side: hardware amortization, electricity, the engineer-hours to build and maintain the serving stack, and the quality difference measured on your evaluation set. Self-hosting wins on sustained high-volume narrow tasks, on data that cannot leave your premises, and on latency floors that a network round trip cannot meet. It loses on bursty traffic, on broad task ranges, and — most often — on the maintenance line that nobody put in the model.

Worked example — the tagging deployment

The task: tag 40,000 wine tasting notes with structured attributes (body, sweetness, oak, primary fruit, drinking window), then keep up with roughly 300 new notes a week. A frontier hosted model does this at about 98% agreement with expert labels, costing roughly $180 for the backfill and $4 a week thereafter.

The self-hosted alternative: an 8B model, INT4-quantized to about 4.5 GB, fine-tuned on 800 expert-labeled notes, running on the 24 GB workstation. Measured agreement: 94.5%. Marginal cost after setup: electricity. Setup cost: roughly 25 engineer-hours.

The honest verdict is that hosted wins this one — $4 a week does not justify 25 hours and a 3.5-point quality loss, and the arithmetic says so plainly. What would flip it: a data residency requirement, a volume 50 times higher, or a latency budget below what the network allows. Naming the flip conditions is the useful part, because it tells you what to re-check when circumstances change rather than re-litigating the decision from scratch.

Module 07 Reading an ML claim

Everything so far has been mechanism. This module is field craft: what to do in the room, when a number is on the slide and a decision is expected by Friday.

The five questions below are not a checklist to memorize. They are consequences of the mechanisms in modules 1 and 2, which means you can regenerate them from first principles when the situation does not match the template. A model is fit to data against an objective and measured on a sample — so ask where the data came from, what the objective's number is being compared against, whether the metric measures the thing that matters, whether the sample was really untouched, and whether that sample resembles yours. Five questions, one derivation.

The habit to bring is the one you already have from practice: a number on a slide is an unauthenticated exhibit. It is not evidence until someone establishes where it came from, who produced it, and under what conditions — and the party offering it bears that burden.

The five questions

Each question falls out of something you already know.

QuestionDerived fromThe trapdoor it guards
1. Provenance. Where did the training and evaluation data come from, who labeled it, and how?A model is a compressed summary of its training data (m1).Contaminated benchmarks; labels of unknown quality; evaluation data that overlaps training.
2. Baseline. What does a simple model score on the same split, and who chose the comparison?A number without a baseline is unpriced (m4).The flattering baseline — beating a straw man, or nothing at all.
3. Metric. What exactly is being measured, and does it track the harm you care about?The loss/metric encodes which errors count (m1).Accuracy on imbalanced classes; a metric chosen after seeing several.
4. Leakage. Could the evaluation data have influenced training or tuning, directly or through the team?Held-out means untouched (m2).Duplication, feature leakage, temporal leaks, and repeated evaluation.
5. Distribution. Does the evaluation data resemble the data this will run on in my organization?Generalization is only claimed within the training distribution (m1, m2).Excellent performance on someone else's data; a demo distribution chosen by the seller.

The order matters in practice. Provenance and baseline can be asked in any meeting without preparation and eliminate a surprising share of weak claims immediately. Metric and leakage require a specific answer and often produce visible discomfort, which is itself information. Distribution is the one that survives every honest answer to the first four — a model can be genuinely good and still be useless on your data — and it is the question that converts an evaluation into a pilot design.

A vendor accuracy claim walked down a flowchart of the five interrogation questions — provenance, baseline, metric, leakage, distribution — each with the trapdoor it guards marked in the right margin, ending at a pilot designed on the buyer's own dataThe claim, as delivered“98% accuracy detecting compliance violations”1. ProvenanceWhere did the data and the labels come from?Trapdoor: contaminated benchmark,labels of unknown quality2. BaselineWhat does a simple model score on this split?Trapdoor: the flattering baseline —a straw man, or none at all3. MetricDoes the measure track the harm you care about?Trapdoor: accuracy at 1% prevalence(flagging nothing scores 99%)4. LeakageCould test data have touched training or tuning?Trapdoor: duplicates, temporal leaks,a test set scored a hundred times5. DistributionDoes the evaluation data resemble ours?Trapdoor: the seller's distribution,curated to a flattering prevalenceSurvives all five — now design the piloton your data, at your prevalenceAny trapdoor open leaves the numberunpriced: ask for the confusion matrix.
Figure 7.1 — The five questions, and the trapdoor each one guards. The claim enters at the top and is walked down the chain; the right margin names the specific failure each question is designed to catch. The questions are ordered by how cheap they are to ask — provenance and baseline need no preparation and eliminate most weak claims on the spot, while distribution is the one that survives honest answers to the other four and converts an evaluation into a pilot. A claim that clears all five is not proven; it has simply earned the cost of testing on your own data.
The load-bearing idea

You are not trying to catch anyone lying. Most inflated ML claims are produced honestly by people who did not run these checks on themselves. The questions are diagnostic, not accusatory, and asking them in a neutral register gets better answers than asking them as a challenge — you want the vendor's team volunteering the weak spot, not defending a position.

The base-rate trap, with arithmetic

Now the claim you will actually be handed: our model detects compliance violations with 98% accuracy.

The claim is true. Work it.

Assume the population it was measured on: 10,000 documents, with a violation prevalence of 1% — so 100 actual violations and 9,900 clean documents. The model has 90% sensitivity (recall) and a 2% false-positive rate. Those are respectable numbers for this kind of system.

Actual violations:        100
  caught (true positives):   90     (90% sensitivity)
  missed (false negatives):  10

Clean documents:        9,900
  false alarms (FP):        198     (2% of 9,900)
  correctly cleared (TN):  9,702

accuracy  = (90 + 9,702) / 10,000 = 97.92%   -> "98% accuracy"
precision = 90 / (90 + 198)       = 31.25%
recall    = 90 / 100              = 90%
A natural-frequency population diagram: 10,000 documents split into 100 violations and 9,900 clean, then into 90 true positives, 10 false negatives, 198 false positives, and 9,702 true negatives, with accuracy and precision computed in the margin10,000 documents100 violations (1%)9,900 clean (99%)90 caughttrue positives10 missedfalse negatives198 false alarmsfalse positives9,702 clearedtrue negativesThe marginsacc = 9,792 / 10,000 = 98%prec = 90/288 = 31%The reviewer's experience: 288 flags, 90 realTwo of every three alerts are false — and a classifier that flagsnothing at all scores 99% accuracy on this same population.
Figure 7.2 — Where 98% accuracy comes from. Ten thousand documents at 1% prevalence split into 100 violations and 9,900 clean. At 90% sensitivity the model catches 90 and misses 10; at a 2% false-positive rate it raises 198 false alarms among the clean documents. Accuracy is (90 + 9,702) / 10,000 = 98%, and it is high because 99% of the population is clean and easy. Precision — what a reviewer actually experiences — is 90 / 288 = 31%. The claim is arithmetically true and operationally misleading, and the degenerate classifier that flags nothing scores 99% on the same data.

Read the last line of the figure again, because it is the whole lesson. A model that flags nothing at all — a single line of code returning false — scores 99% accuracy on this population. The vendor's 98% is worse than doing nothing, as measured by the metric they chose to report.

Meanwhile the operational reality is 288 flagged documents of which 198 are false alarms. If review takes 25 minutes per document, that is 120 hours per 10,000 documents — two-thirds of it (about 82 hours, the 198 false alarms) wasted — and reviewer trust in the queue erodes within weeks — the well-documented failure pattern in alert-driven work, where a two-thirds false rate teaches reviewers to skim.

Anti-pattern: accuracy on imbalanced classes

Symptom: accuracy reported as the headline metric for a problem where the positive class is rare — fraud, violations, defects, churn, disease. Mechanism: accuracy is dominated by the majority class, so it is high whenever the base rate is low, regardless of whether the model finds anything. Corrective: demand the confusion matrix at your prevalence, then compute precision and recall yourself. Two follow-ups make the point without confrontation: what does the all-negative classifier score on this data, and what is precision at the operating threshold you would ship?

Note the phrase "at your prevalence." Precision depends on the base rate, so a vendor measuring on a curated set with 20% violations will report precision far above what you will see at 1%. The confusion matrix must be computed on a population with your prevalence, or converted to it.

Cross-examining the benchmark

The base-rate question handles the metric. Provenance handles the number's origin, and it is asked the way foundation is laid for an exhibit: not "is this true" but "who made this, from what, and under what conditions."

  • Who assembled the evaluation set, and when? A vendor-assembled set is not disqualifying, but it changes what the number means, and the assembly date matters for the next question.
  • Could the evaluation data have appeared in training? This is benchmark contamination, and for anything built on a model pretrained on web-scale data it is the default hypothesis rather than an exotic risk. Public benchmarks are on the public internet. The check is a private evaluation set the vendor has never seen.
  • Who chose the baseline, and would a competent adversary have chosen it? "Three times better than the legacy system" invites the question of whether the legacy system was a serious comparator or a decade-old rules engine nobody defends. The honest baseline is the best cheap alternative, not the incumbent.
  • What was the metric before it was this one? Metrics get selected after results are seen. Asking which metrics were computed, in what order, is the ML equivalent of asking what else the expert wrote before this report.
  • What is the failure distribution? Not the aggregate error rate — the shape. Which cases fail, and are they clustered in a segment that matters to you? A vendor who cannot describe their failure modes has not examined them.
From your other life

This is voir dire on an expert's methodology, and the transferable instinct is that the weakness is rarely in the conclusion — it is in the sampling, the instrument, and the selection of what got measured. The corresponding tell also transfers: a competent, honest team answers these questions quickly and volunteers the caveats, because they already asked themselves. Hesitation on "who assembled the evaluation set" is not proof of anything, but it tells you where to dig.

Anti-pattern: benchmark trust without provenance

Symptom: a purchase or architecture decision made on public benchmark scores or a leaderboard position. Mechanism: public benchmarks are in the training data of anything trained on web crawls, and they measure a task distribution assembled by someone else for someone else's purpose. Corrective: a private evaluation set drawn from your own data, never shared with the vendor, run under conditions you control. Benchmarks are a prior for narrowing a shortlist; they are not evidence about your task.

Distribution match: will it work on your data

Suppose every previous answer is honest. Provenance is clean, the baseline is serious, the metric is precision at a stated threshold, the holdout was untouched. The model is genuinely good — on the vendor's distribution.

Your documents are written by your people, in your jargon, under your retention policy, with your prevalence of the thing being detected. A model trained on financial services communications and evaluated on financial services communications tells you very little about a logistics company's Slack. The only claim that matters is the one measured on your data, and no amount of interrogation substitutes for measuring it.

So the interrogation ends in a pilot design, and the terms of the pilot must be fixed before results exist — which is the same discipline as module 2's test-set policy, applied to a commercial negotiation.

Pilot termWhat it must sayWhy it is negotiated in advance
SampleN documents drawn by you, by a stated sampling rule, from a stated period.A vendor-selected sample is a demo. A convenience sample of easy cases is a demo you built yourself.
LabelsGround truth produced by your experts, with the adjudication procedure and inter-rater agreement recorded.Unstated label quality caps every metric and becomes the argument when results disappoint.
Metric and thresholdPrecision and recall at the operating point you would actually ship, at your prevalence.Otherwise the metric gets chosen after the results, and it will be the flattering one.
Success criterionA number that constitutes a pass, written down.Without it, a mediocre result becomes a discussion about promise rather than a decision.
Failure reviewYou get the failure cases, not just the aggregate.The failure shape tells you whether the errors are tolerable or concentrated where you cannot afford them.
On tone

Vendors worth buying from welcome this. A team confident in their system would rather be measured on your data than argue about theirs, and the pilot gives them a reference case. Resistance to a well-specified pilot is the strongest single signal you will get in the entire evaluation — stronger than any number on any slide.

Module 08 The anti-pattern catalog

Everything in this module except one section is consolidation. The six failures below have already appeared in their home modules as caution callouts and quiz distractors; the value of gathering them under stable names is that named things get recognized faster, and recognition speed is what matters when a plan is on a slide and a decision is expected.

Two things here are genuinely new. The first is distribution shift, which is the failure mode that arrives after launch, when nobody is looking and no alarm fires. The second is the closing compression: the course reduced to the questions you actually carry, each traceable to the mechanism it came from — the demonstration that the interrogation was derivable all along.

The six, named

Each entry is symptom, mechanism, corrective — and a pointer back to the module that explains why.

Anti-patternSymptom in the wildCorrectiveModule
Accuracy on imbalanced classesAccuracy is the headline metric for a rare event — fraud, violations, defects, churn.Confusion matrix at your prevalence; compute precision and recall yourself; ask what the all-negative classifier scores.m7
The demo-to-production leapA commitment justified by demo performance, with no measurement on your own distribution.A pilot on a buyer-selected sample with metric, labels, and pass criterion fixed in writing beforehand.m2, m7
Fine-tuning as a reflex"We'll fine-tune it on our domain," proposed before prompting or retrieval was seriously attempted, with no classification of the gap.Written knowledge-vs-behavior triage; fresh facts route to retrieval; tuning budget released only after cheaper interventions were measured.m5
Neural nets on small tabular dataA deep network proposed for a few thousand rows of mixed structured features, justified by sophistication.Linear baseline plus a gradient-boosted ensemble first; the deep model must beat both on held-out data by a margin worth its cost.m4
Benchmark trust without provenanceA decision made on leaderboard position or a public benchmark score.A private evaluation set from your own data that the vendor has never seen; benchmarks narrow a shortlist, they do not settle it.m7
Model size equals capabilityModel selection by parameter count or general rank — "we need at least a 30B for this."Benchmark candidates on your own task set at deployment precision; a tuned or distilled small model often wins its specialty outright.m6

Three of these have the same underlying shape, and noticing it makes them easier to catch: the demo-to-production leap, benchmark trust, and accuracy-on-imbalanced-classes are all cases of accepting a measurement taken under conditions that differ from the conditions you will operate in. The other three — fine-tuning as reflex, neural nets on small tables, size equals capability — share a different shape: choosing an instrument by its impressiveness rather than by its fit to the problem. Two failure families, six named forms.

Distribution shift: the slow failure

Every failure so far is detectable before launch. This one is not, because it does not exist before launch.

A model is a static file. It does not degrade, corrode, or drift. The world drifts. Your product adds a segment, a competitor changes their pricing and your customers' language changes with it, a regulation shifts what counts as a violation, a new integration starts sending documents in a format that did not exist during training. The model keeps applying the regularities it compressed from data that no longer describes the present, and its error rate rises quietly.

What makes distribution shift operationally nasty is that nothing pages anyone. The service is healthy, latency is flat, no exception is thrown. Predictions are still returned, confidently, and they are wrong more often than they used to be. In most organizations the discovery mechanism is a downstream human noticing that the outputs have felt off for a while.

Two offset distribution curves showing training data and drifted production data, with model error rising as the gap widens and a monitoring threshold triggering re-evaluation before the error becomes visible in business metricsmonths since launch →training distributionproduction, month 4production, month 9input distribution moves; the model does notmodel error →drift monitor fires herea human noticesThe world moves; the weights do not
Figure 8.1 — Drift, and the gap between the two discovery times. The training distribution (solid) is fixed at the moment of training. Production inputs shift away from it month by month, and model error climbs in the widening gap with no error raised anywhere — the service stays healthy while the predictions get worse. Two vertical lines mark the discovery times: an input-distribution monitor fires around month 7, and an unaided organization notices around month 10. The distance between them is the value of the monitoring, and it is decided at launch or not at all.

Monitoring for it does not require labels, which is the part teams get wrong. You cannot compute accuracy in production without ground truth, but you can watch the inputs, and inputs are free. Track the distribution of key features and the rate of new categories; for text, track the share of inputs whose embedding sits far from every training cluster. Track the model's own output distribution too — a violation detector whose flag rate drifts from 2.4% to 3.9% has told you something even if you cannot yet say what.

Then commit at launch to two things: a re-evaluation cadence (quarterly, with a freshly labeled sample), and a trigger threshold that pulls the re-evaluation forward. The cost of labeling 300 documents a quarter is small and known. The cost of finding out in month ten is neither.

The un-snowable posture

The course reduces to three mechanisms and the questions they generate. Everything else was elaboration.

MechanismThe questions it generates
A model minimizes a measured loss on data.What is it optimizing, and is that what we want? Where is the proxy gap? What data was it fit to, who labeled it, and how?
Only untouched data shows generalization.What is the number on data the model never saw? How do you know it never saw it? How many times was the holdout used? Does the evaluation population look like ours?
Embeddings turn meaning into geometry.What notion of similar did the training objective install? Is this a nearest-neighbor problem wearing a costume? Where are the hard constraints being enforced?

Three more questions come from the economics rather than the mechanisms, and they are the ones that most often change a decision: what does the simple version score? — the baseline demand that prices every claim. What does this cost per unit at our volume, and what does the cheaper option lose? — the escalation discipline from module 4's routing. And what would tell us this stopped working? — the monitoring commitment, made at launch or not at all.

The load-bearing idea

You were never going to out-argue a specialist on architecture, and you never needed to. The questions that decide whether an ML claim is worth acting on are questions about measurement, comparison, and fit — and those are questions you can ask from first principles, in the room, with no notebook open. Being un-snowable is not knowing more than the vendor. It is knowing which four questions a good answer has to survive.

Where this goes next

Guide Nº 03 (Evals) takes the module-2 discipline up a layer to application-level evaluation of LLM systems. The retrieval fork from module 5 lives there too. What this guide adds underneath both is the reason the rules are what they are — so when a situation appears that no checklist covers, you can derive the right question instead of reaching for the nearest one.

Concept index

Model
A parameterized function whose parameters are set by data rather than by a programmer.
Parameters (weights)
The adjustable numbers inside a model that training sets.
Loss function
The formula that converts prediction errors into the single number training minimizes.
Gradient descent
The update rule that nudges each weight in the direction that reduces loss, repeatedly.
Learning rate
The step size of each gradient-descent nudge; too large diverges, too small crawls.
Generalization
Performing well on data the model has never seen — the only meaning of learned.
Memorization
Storing training answers rather than compressing their regularities; invisible on training data.
Capacity
A model's ability to fit complexity — including, past a point, noise.
Overfitting
Improving on seen data while worsening on unseen data.
Train/validation/test split
The partition that separates fitting, tuning, and final honest measurement.
Holdout
Data kept untouched until final evaluation; the admissible evidence.
Data leakage
Any path by which evaluation data influences training or tuning, inflating results.
Temporal leakage
Training on the future to predict the past via careless time splits.
Early stopping
Halting training where validation loss bottoms out, before memorization.
Embedding
A learned mapping of discrete things into vectors where distance means relatedness.
Vector space
The geometric arena embeddings live in; its structure encodes the training objective.
Cosine similarity
Similarity as the angle between vectors, ignoring magnitude.
Nearest-neighbor search
Finding the stored vectors closest to a query vector; the core embedding operation.
ANN index
An approximate nearest-neighbor structure trading exactness for query speed.
Semantic search
Retrieval by embedding similarity rather than keyword match.
Clustering
Grouping points by proximity in embedding space; geometry, not meaning, until labeled.
Linear regression
A model whose readable weights make it both baseline and witness.
Logistic regression
The linear model for classification; outputs calibrated probabilities.
Decision tree
A model that partitions feature space with learned threshold splits.
Gradient-boosted trees (GBM)
An ensemble of small trees, each correcting its predecessors; the tabular default.
Baseline
The simple model any claimed improvement must beat to mean anything.
Tabular data
Structured rows-and-columns data — where classical models usually win.
Fine-tuning
Continued gradient descent on a narrower objective; changes behavior more reliably than knowledge.
LoRA
Low-rank adapters trained on a frozen base model — most of the tuning at about 1% of the parameters.
Preference optimization
RLHF/DPO-style training that reshapes which existing outputs a model prefers.
Catastrophic forgetting
Degradation of prior capabilities caused by aggressive fine-tuning.
Quantization
Storing weights in fewer bits to cut memory and latency at a measurable quality cost.
Distillation
Training a small student model to imitate a large teacher within a taught distribution.
Precision
Of everything flagged, the fraction actually positive.
Recall (sensitivity)
Of everything actually positive, the fraction flagged.
Base rate
The prevalence of the condition — the number that makes or breaks an accuracy claim.
Confusion matrix
The 2x2 table of true/false positives and negatives behind every honest metric.
Benchmark contamination
Test data present in training data, silently inflating benchmark scores.
Distribution shift
Production data drifting away from training data; the slow failure mode.

This is the complete text of the course. With JavaScript enabled, this same page runs the interactive edition — a self-diagnostic that reorders the syllabus around your gaps, knowledge checks, applied worksheets with model answers, and a spaced-repetition review queue — with progress saved locally in your browser.