JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

Past Accuracy: Metrics for Detection, Segmentation, Generation, and Confidence

Real vision tasks are not just classification — learn the metrics that score boxes, masks, generated images, and whether a model's confidence can be trusted.

From labels to locations: overlap with IoU

In the last guide we only ever asked one question: did the model name the right class? That works for image classification, where the whole picture gets a single label. But most real vision tasks also care about where. An object detector does not just say 'there is a cat in this photo' — it draws a box around the cat. Now there are two ways to be wrong: you can get the label wrong (it is a dog, not a cat), or you can get the label right but draw the box in the wrong place (you boxed the cat's tail and called it a cat). To grade a detector fairly we need a number that measures how well a predicted box lines up with the true box.

The standard tool is Intersection over Union, or IoU. Picture two sticky notes thrown onto a desk so they partly overlap. The intersection is the patch where both notes cover the desk — the bit you would see if you held them up to the light and looked for the doubly-covered region. The union is the total area the two notes cover together, counting that shared patch only once. IoU is simply the shared patch divided by the total covered area. If the two notes land exactly on top of each other, the shared patch is the total area, so IoU = 1. If they barely touch, the shared patch is tiny compared to the total, so IoU is close to 0. The same idea works for a predicted detection box and the ground-truth box.

A predicted box and a ground-truth box: IoU is their overlap area divided by their combined area.

Two overlapping rectangles with the intersection region shaded and the surrounding union region outlined.

\text{IoU} = \dfrac{\text{area}(P \cap G)}{\text{area}(P \cup G)}

Intersection over Union of a predicted box P and a ground-truth box G.

Let us read this symbol by symbol. P is the box the model predicted; G is the ground-truth box a human drew. The symbol ∩ means intersection (the overlap), and ∪ means union (everything either box covers). The numerator, area(P ∩ G), is the overlap area — how much of the prediction lands on the real object. The denominator, area(P ∪ G), is the combined area — the prediction plus the truth, minus the overlap so we do not count it twice. Now a concrete number. Say the predicted box has corners (0,0) to (6,4), so it is 6 wide and 4 tall: area 24. The ground-truth box runs from (2,0) to (8,4): also 6 by 4, area 24. They overlap from x = 2 to x = 6 (width 4) and y = 0 to y = 4 (height 4), so the intersection is 4 × 4 = 16. The union is 24 + 24 − 16 = 32. Therefore IoU = 16 / 32 = 0.5. Because the overlap can never exceed the union, IoU is always between 0 and 1. An IoU of 0.5 looks like two boxes that share roughly half their footprint — clearly the same object, but the box is loose. An IoU of 0.9 looks like the predicted box is almost perfectly snapped onto the truth, off by just a thin margin.

IoU gives us a smooth overlap score, but to count detections as right or wrong we need a yes/no decision. So we pick a threshold — classically IoU > 0.5 counts as a 'hit'. A detection with the correct label and IoU above the threshold becomes a true positive; a box with too little overlap (or the wrong label) is a false positive; a real object with no good matching box is a false negative. If those three terms feel familiar, they should: they are exactly the cells of the confusion matrix from the last guide, now decided by location instead of pure class. The threshold is a knob, though — slide it to 0.75 and you demand tighter boxes, which is why the choice of IoU threshold matters so much for the next metric, mean IoU and the detector report card we build next.

Mean Average Precision: the detector's report card

mAP is the metric every detection paper reports, and it is also the one beginners find most slippery — so let us build it one layer at a time, reusing pieces you already own. Layer one: fix an IoU threshold (say 0.5). Now every detection the model emits is cleanly a true positive or a false positive, exactly as we just set up. Layer two: a detector also attaches a confidence to each box. If we set a high confidence bar we keep only the surest boxes (few false positives, but we miss objects); lower the bar and we accept more boxes (we catch more objects, but let junk through). Sweeping that confidence bar from high to low traces out a whole curve of precision and recall values — the precision-recall curve — which is the same precision and recall you learned in Guide 1, just plotted as the threshold moves.

Each point on the precision-recall curve comes from one confidence threshold; AP is the area underneath it.

A curve with recall on the x-axis and precision on the y-axis, generally sloping down to the right, with the area under it shaded.

\text{AP} = \int_0^1 p(r)\,dr, \qquad \text{mAP} = \frac{1}{C}\sum_{c=1}^{C} \text{AP}_c

Average Precision is the area under one class's PR curve; mAP averages AP over all classes.

Layer three, the formula. In the left expression, p(r) is the precision the model achieves at recall level r, and the integral ∫ from 0 to 1 just means 'the area under that precision-recall curve as recall runs from 0 (no objects found) to 1 (every object found)'. That area is the Average Precision (AP) for one single class — one number that rewards staying precise even as you push recall up. In the right expression, C is the number of object classes (cat, dog, car, …), the symbol Σ means 'add up', and AP_c is the AP computed for class c on its own curve. So mAP — mean Average Precision — is literally the average of the per-class APs: add up AP over all C classes and divide by C. One report-card number for the whole detector.

# One class, "cat". The test set contains 3 real cats (so recall is out of 3).
# The detector emits 5 boxes, sorted by confidence, highest first.
# Each box is TP if it matches an unused GT cat with IoU > 0.5, else FP.
#
#  rank  conf   TP/FP   cumTP  cumFP   precision = TP/(TP+FP)   recall = TP/3
#   1    0.95    TP       1      0         1/1 = 1.00             1/3 = 0.33
#   2    0.90    FP       1      1         1/2 = 0.50             1/3 = 0.33
#   3    0.80    TP       2      1         2/3 = 0.67             2/3 = 0.67
#   4    0.70    TP       3      1         3/4 = 0.75             3/3 = 1.00
#   5    0.60    FP       3      2         3/5 = 0.60             3/3 = 1.00
#
# Reading top-to-bottom = lowering the confidence threshold one box at a time.
# Each row is one point (recall, precision) on the PR curve.
Walking five ranked detections: precision and recall update as each box is accepted.

Watch the table move. Accept only the top box (a TP): precision is a perfect 1.0 but recall is just 0.33 — we found one of three cats. The second box is a FP, so precision drops to 0.5 while recall stays put. Boxes three and four are TPs, lifting recall to 1.0 while precision settles at 0.75. To get AP we take the area under this curve. A common rule is to use the best precision still achievable at each recall or beyond: precision stays at 1.0 up to recall 0.33, then 0.75 the rest of the way. So AP ≈ (1.0 × 0.33) + (0.75 × 0.67) ≈ 0.33 + 0.50 = 0.83 for the cat class. Repeat for dog, car, and every other class, then average those APs and you have mAP. One refinement you will meet everywhere: the COCO benchmark does not stop at IoU > 0.5. It computes mAP at ten IoU thresholds from 0.5 to 0.95 and averages them — written mAP@[.5:.95]. Why? Because a detector that draws sloppy-but-passable boxes scores fine at 0.5 but collapses at 0.9, so averaging over tighter IoU thresholds rewards models whose boxes truly hug the object.

Scoring masks: mean Intersection over Union

Segmentation goes one step finer than detection: instead of a box, it assigns a class label to every single pixel — this pixel is road, that one is sky, that one is car. The obvious score would be 'fraction of pixels labeled correctly' (pixel accuracy), but that walks straight into the imbalance trap from Guide 1. Imagine a photo that is 90% sky. A lazy model that paints the whole image as sky already scores 90% pixel accuracy while completely missing the bird, the wire, and the cloud you actually cared about. The fix is the same idea we used for boxes — overlap, not raw counts — just applied to pixels instead. We compute IoU per class and then take the mean across classes, written mean IoU (mIoU).

Semantic segmentation: every pixel is colored by its class. mIoU scores how well predicted regions overlap the true regions.

An image where each region (road, sky, car, person) is filled with a distinct flat color according to its class.

\text{IoU}_k = \dfrac{TP_k}{TP_k + FP_k + FN_k}, \qquad \text{mIoU} = \frac{1}{K}\sum_{k=1}^{K}\text{IoU}_k

Per-class IoU counted over pixels, then averaged across the K classes.

# A tiny 4x4 image (16 pixels). Two classes: cat (C) and background (.).
#
#   GROUND TRUTH          PREDICTION
#     . . . .               . . . .
#     . C C .               . C C C     <- one extra pixel wrongly called cat (FP)
#     . C C .               . . C .     <- one true cat pixel missed (FN)
#     . . . .               . . . .
#
# For class "cat":
#   TP_cat = truly cat AND predicted cat   = 3 pixels
#   FP_cat = predicted cat but NOT cat     = 1 pixel
#   FN_cat = truly cat but predicted other = 1 pixel
#
#   IoU_cat = 3 / (3 + 1 + 1) = 3/5 = 0.60
Per-class IoU on a 4x4 pixel grid: it is the box IoU idea counted pixel-by-pixel.

Reading the formula with the grid in hand: for a class k, TP_k is the number of pixels that are truly class k and predicted class k (the overlap), FP_k is pixels predicted k but actually something else (over-painting), and FN_k is pixels that truly are k but were given another label (missed). The denominator TP_k + FP_k + FN_k is exactly the pixels that are predicted-or-truly class k — the pixel union, just as area(P ∪ G) was the box union. In our grid the cat IoU is 3/(3+1+1) = 0.60. mIoU then averages these per-class IoUs over all K classes (here K = 2: cat and background), dividing by K. Here is why the union denominator is the anti-cheat device: if a model floods the image with a common class to boost its recall, every wrong pixel it paints lands in FP and inflates the denominator, dragging that class's IoU back down. Concretely, our lazy 'predict everything as background' model would score 12/16 = 0.75 pixel accuracy yet earn a cat IoU of exactly 0, collapsing mIoU. Accuracy applauds the cheat; mIoU exposes it.

One distinction to keep straight. Semantic segmentation only asks 'what class is this pixel?' — all cats are simply 'cat', even if three of them touch and merge into one blob. Instance segmentation goes further and separates each individual object — cat #1, cat #2, cat #3 — even when they overlap. mIoU is the workhorse metric for semantic segmentation, because it scores class regions and does not care about telling individuals apart. Instance segmentation, by contrast, is graded much more like detection — with per-instance masks matched by IoU and scored with mAP-style Average Precision. So the metrics in this guide are not separate islands: IoU is the shared atom, and detection, semantic, and instance segmentation each assemble it differently.

Semantic vs instance segmentation: same pixels, but instance separates each object — and is graded more like detection.

Side-by-side: on the left all sheep share one color (semantic); on the right each sheep has its own color (instance).

Judging images that have no label: FID for generation

Now the hardest case. A generative model — a GAN or a diffusion model — produces brand-new images of, say, faces or bedrooms that were never in any dataset. There is no ground-truth answer to compare against, so accuracy, IoU, and mAP all become meaningless: which 'correct' face was the model supposed to draw? We need a different yardstick, and it starts from naming what 'good' even means. We want two things at once: the images should be realistic (each one looks like a plausible real photo) and diverse (the model should produce many different faces, not the same face over and over — a failure called mode collapse). The trick that captures both is to stop grading individual images and instead compare the whole distribution of generated images against the distribution of real ones.

A GAN pits a generator against a discriminator; we still need a metric to say how close its output distribution is to real data.

A diagram of a generator producing fake images and a discriminator trying to tell real from fake.

The standard distribution-comparison metric is the Fréchet Inception Distance (FID). The recipe has three moves. First, you cannot compare images pixel-by-pixel — two photos of the same dog shifted by one pixel are 'far apart' in raw pixels but identical in content. So you pass every real image and every generated image through a pretrained network (the Inception network, trained on ImageNet) and grab an internal feature vector for each — a list of numbers describing high-level content like 'furry', 'has eyes', 'outdoor'. Second, you summarize each cloud of feature vectors — the real cloud and the fake cloud — as a multidimensional Gaussian (a bell-shaped blob with a center and a spread). Third, you measure the distance between those two Gaussians. Diffusion models, which now lead image generation, are graded by exactly this same FID procedure.

A diffusion model denoises random noise into an image; FID checks whether its output distribution matches real data.

A sequence showing pure noise progressively denoised into a clear generated image.

\text{FID} = \lVert \mu_r - \mu_g \rVert^2 + \operatorname{Tr}\!\left(\Sigma_r + \Sigma_g - 2\,(\Sigma_r \Sigma_g)^{1/2}\right)

FID: distance between the real Gaussian (μ_r, Σ_r) and the generated Gaussian (μ_g, Σ_g). Lower is better.

You do not need to compute matrix square roots by hand — but you should be able to read what each piece means. μ_r and μ_g (the Greek letter mu) are the mean feature vectors of the real and generated sets: the 'average content' of each cloud, its center of mass. The first term, ‖μ_r − μ_g‖², is the squared distance between those two centers — it asks 'on average, does the fake content sit in the same place as the real content?' If your generator makes faces that are systematically too smooth or too bright, the centers drift apart and this term grows. Σ_r and Σ_g (capital sigma) are the covariances: they describe how spread out and correlated each cloud is — in other words, how diverse the set is and which features vary together. The trace term, Tr(Σ_r + Σ_g − 2(Σ_r Σ_g)^{1/2}), compares those spreads: it is near zero when the two clouds have the same shape and variety, and large when they differ — for example when mode collapse shrinks the fake cloud so it covers far less variety than the real one. Add the two terms and you get a single number where lower means the two distributions sit closer and overlap more — so the generated images are both more realistic and more diverse. An FID near 5 means the clouds nearly coincide; an FID of 80 means they are far apart.

Is the confidence trustworthy? Calibration

At the end of the last guide we hinted that a model's confidence number deserves its own scrutiny. Here is the payoff. A classifier does not just say 'cat' — it says 'cat, with 90% confidence'. Calibration asks whether that 90% can be taken at face value. The clean definition: a model is calibrated if, among all the predictions it makes with confidence p, the fraction that actually turn out correct is exactly p. So if you gather every prediction your model labeled '70% sure' and 70% of them are right, that 0.7 was honest. If only 50% of them are right, the model claimed 70% but earned 50% — it was overconfident, and its confidence is a lie you cannot safely act on.

The picture that makes this vivid is the reliability diagram. Put the model's claimed confidence on the x-axis and the observed accuracy on the y-axis. To build it, sort predictions into confidence bins — all the '50–60% sure' ones together, the '60–70%' ones together, and so on — and for each bin plot a dot: average claimed confidence across, true accuracy up. A perfectly calibrated model lands every dot on the 45-degree diagonal, where claimed equals observed. Dots sagging below the diagonal mean the model claimed more confidence than it deserved (overconfident); dots floating above mean it was underconfident, more right than it admitted.

A well-known and slightly uncomfortable finding: modern deep networks are typically overconfident. The big accurate models that win benchmarks tend to blurt out 99% confidence even when they are wrong far more than 1% of the time — their dots sag below the diagonal. Curiously, older, smaller networks were often better calibrated; something about the scale and training of modern nets pushes their probabilities toward the extremes. So high accuracy and good calibration are genuinely separate qualities: a model can be right most of the time and still be a terrible judge of when it is about to be wrong.

\text{ECE} = \sum_{b=1}^{B} \frac{n_b}{N} \,\bigl| \operatorname{acc}(b) - \operatorname{conf}(b) \bigr|

Expected Calibration Error: the bin-weighted average gap between observed accuracy and claimed confidence.

The reliability diagram is a picture; Expected Calibration Error (ECE) squeezes it into one number — the average vertical gap between the dots and the diagonal. Symbol by symbol: we split predictions into B confidence bins, and b indexes one bin. n_b is how many predictions fall in bin b, and N is the total number of predictions, so n_b / N is the fraction of predictions in that bin — its weight, so crowded bins count more than nearly-empty ones. acc(b) is the observed accuracy inside the bin (how many were actually right) and conf(b) is the average confidence the model claimed in that bin. The absolute value |acc(b) − conf(b)| is the gap between honesty and claim for that bin, and Σ adds up these gaps weighted by how common each bin is. A tiny example: suppose one bin holds 100 of your 1,000 predictions, the model claimed 0.9 confidence there, but only 70% were right. That bin contributes (100/1000) × |0.70 − 0.90| = 0.1 × 0.20 = 0.02 to the ECE. Sum such contributions over all bins; ECE = 0 is perfect honesty, and bigger means more self-deception. A common, cheap fix is temperature scaling: after training, divide the model's raw output scores (logits) by a single learned number T > 1 before turning them into probabilities. This softens overconfident spikes toward more honest values without changing which class is predicted, so accuracy stays the same while calibration improves.

Why obsess over a model's honesty about itself? Because in any system that acts on a prediction, the confidence is the steering wheel for risk. A self-driving car that is genuinely unsure whether the shape ahead is a pedestrian must know it is unsure so it can brake or hand control back to a human; an overconfident '99% empty road' is exactly the lie that kills. A medical model that flags 'probably benign' had better mean it. Calibration is the bridge to trustworthy AI, and it leads directly into the next guide's question: when the input is something the model has never seen — out-of-distribution — a well-calibrated model should lower its confidence rather than confidently hallucinate. We will build that out-of-distribution detection on top of this model calibration foundation.

How metrics get gamed

We will close by raising the maturity level from 'which metric?' to 'can I trust this number at all?' The governing idea is Goodhart's law: *when a measure becomes a target, it ceases to be a good measure.* The moment a number like accuracy, mAP, or FID becomes the thing everyone optimizes and competes on, people start chasing the number rather than the underlying quality it was meant to track — and the number quietly stops meaning what you think it means.

Vision is full of concrete examples. Benchmark overfitting: if everyone reports on the same fixed test set for years, models slowly bend to the quirks of that one set and the leaderboard climbs without real-world ability rising. Tuning on the test set: if you peek at test results, tweak the model, and repeat, the test set has secretly become training data and your reported score is fiction. Cherry-picking the IoU threshold: report mAP only at the loose 0.5 threshold and a sloppy-box detector looks great — quietly dropping the [.5:.95] average hides that its boxes are mushy. Gaming FID: report it on whatever sample size flatters you, since FID improves as samples grow, or generate thousands of images and show only the prettiest. Each move technically reports a 'real' metric while telling a misleading story.

Overfitting in miniature: a model can memorize a benchmark and post great numbers without learning anything that generalizes.

A curve that fits training points perfectly but wiggles wildly between them, missing the true underlying trend.

  1. Hold out a true test set: never look at it during development, and use it exactly once for the final number.
  2. Report confidence intervals or error bars, not a single decimal — a 0.2-point mAP win inside the noise is not a win.
  3. Show multiple metrics that can disagree (e.g. mAP@[.5:.95] alongside [email protected], or mIoU alongside pixel accuracy) so a single flattering one cannot hide a flaw.
  4. Fix and disclose your protocol: the exact IoU thresholds, the FID sample size, the dataset split — so others can reproduce and compare fairly.
  5. Report failure cases, not just the wins: show where the model breaks, because the gap between benchmark and reality lives there.

This is the bridge into the rest of the track. Every metric in this guide assumes the test data looks like the training data — same cameras, same lighting, same world. A model can ace accuracy, mAP, mIoU, FID, and even calibration on its benchmark and still fall apart the instant the input changes: a few pixels nudged by an adversary, a snowstorm the training set never contained, a face from a group the data under-sampled. Strong metrics tell you a model is good on the test you gave it — they say nothing about what happens when the world shifts. That fragility is exactly what the next three guides take apart, in order: adversarial examples, distribution shift and out-of-distribution detection, and finally fairness, interpretability, and trust.