learn-data-centric-ai-with-phoebe / Session 6 of 6
Learn Data-Centric AI with Phoebe · Session 6 of 6

The data-edit spec

Five sessions of edits are worth very little if nobody can say afterwards which rows changed, why, and whether the gain was real. Tonight is the capstone. First you beat the bench with data edits only, the model untouched, and learn to read a win honestly when one test digit is 0.2 points. Then you write the edit down as a one-page spec: what was frozen, what rule the labels follow, which detector flagged which rows, who reviewed them, and what the result does and does not prove. Last, you audit the detector without an answer key and set the rule that tells you when to stop cleaning.

🟠 Capstone ML engineers, data leads, labelling leads Python, the session 4 bench 45 min
0-3 · Welcome 3-18 · Beat, write, audit 18-40 · Build-along: the spec 40-45 · Q&A
Part 0

Where we start

You have a frozen model, a locked test set, a declared noise plant, a detector that finds wrong labels out of sample, a bench that scores every edit, and a way to find the weak slice without peeking. What you do not have yet is the document. A data edit that lives in someone's notebook is gone the day they change teams. A data edit written as a spec can be audited by a reviewer, rerun by a stranger, and reused when the next model arrives.

🎫 Clear all three quiz questions to stamp your passport Live = presented in the 45 minutes Self-study = the full depth, after class ★ Build-along = run the code yourself

★ What you walk out with tonight. A combination of data edits that takes the frozen model to 96.6 percent against a 91.4 percent baseline, the discipline to judge it against twenty-seed means rather than one lucky digit, a filled one-page data-edit spec another person could rerun, a 20-flag audit that estimates the detector's precision without an answer key, and a stopping rule written down before the next cleaning pass starts.

Part 1 · covers beating the benchmark by data edits only

Beat the bench, model untouched

5 min live

The Data-Centric AI Competition of 2021 set the format this capstone copies: "improve a dataset given a fixed model", scored on accuracy, submissions closed on 4 September 2021. Tonight's version runs on the session 4 bench. The best preset on the 800 rows alone is 96.0 percent, 480 of 500, from relabelling the flags and shifting the weakest digit. The best combination anywhere on the bench is 96.6 percent, 483, on the 1,297 rows with relabelling and the ambiguous rows dropped. The ceiling, the same model on the true labels, is 97.8 percent. The hard part is not finding a higher number; it is knowing whether a higher number means anything.

500 TEST DIGITS: EVERY ONE IS WORTH 0.2 POINTS scale: 60px = 1 point · rust band = one test digit, 12px wide THIS SEED, 20210921 TWENTY SEEDS, MEANS 88 90 92 94 96 98 100 baseline, 457 of 500 91.4 best on the 800 alone, 480 96.0 best overall, 483 96.6 97.8 ceiling: true labels, 489 one test digit = 0.2 points one digit less is 96.4, a different edit 88 90 92 94 96 98 100 baseline mean 89.97 relabel · relabel + shift · collect + clean 94.45 · 94.52 · 94.60 all three fit inside one digit 97.26 reference mean, true labels Seeds 20210904 to 20210923. The 96.6 combination was not in the sweep: one seed, promising, not proven.
🔍 Click to zoom - three edits that look different on one seed sit within 0.15 points of each other over twenty; judge a win against the band, not the bar
LiveThe capstone rules2 min▶

Only data edits. Relabel, remove, drop ambiguous rows, add shifted copies, add the 497 extra rows: anything the knobs on the session 4 bench allow, in any combination.

The model and the seed are frozen. kNN with k = 10, squared distance on the 64 raw pixels, seed 20210921 for the split and the plant. If you want to try k = 5, that is a model-centric experiment and belongs in a different document.

The test set is untouched. Not relabelled, not filtered, and not used to pick the edit. Reading per-digit test accuracy after the choice is fine; choosing by it is not.

Every edit is logged. A row that changed without a line in the log is a row nobody can defend. Part 2 is that log.

LiveHow to read a win2 min▶

On 500 test digits, one digit is 0.2 points. So 96.6 against 96.4 is one digit, and one digit on one seed is not a win. It could flip if the split moved. The honest comparison is against the twenty-seed sweep, where it exists: relabel averages 94.45, relabel plus shift 94.52, and collect plus clean 94.60. Those three edits look different on the shipped seed, and over twenty seeds they are within 0.15 points of each other, less than one test digit. Treat them as about equal.

The 96.6 combination beats the best 800-row preset by three digits, 0.6 points, on one seed. That is a promising lead, not a finding: the sweep did not run it. Two combinations tie at 483, the 1,297 rows with relabel and drop ambiguous, and the 1,297 with remove, drop ambiguous and shift. When two edits tie, prefer the one with fewer steps and fewer rows: it is cheaper to explain and to rerun.

Self-studyWhy the ceiling is not 100 percent2 min▶

Trained on the true labels, the frozen model still misses 11 of the 500 test digits: 489 correct, 97.8 percent. Those misses are not label errors in training, because there are none. They are digits the model cannot separate: a 4 whose ten nearest training images happen to be 9s, a sloppy 8 that sits in the 3s' neighbourhood. No data edit to the labels can fix them. Only more coverage near those shapes, or a different model, could.

That makes the gap you are allowed to close 32 digits, from 457 to 489, and not 43. On this seed the best combination closes 26 of them. Quoting "96.6 against a perfect 100" would overstate what is left for the data to do.

Real world

The competition that fixed the model. DeepLearning.AI and Landing AI ran the Data-Centric AI Competition on a noisy set of handwritten Roman numerals, with every entrant training the same model and changing only the data: "fixing incorrect labels, adding examples that represent edge cases, apply data augmentation". Submissions closed on 4 September 2021 and were scored on accuracy. The fixed model is reported as a cut-down ResNet50 on 32 by 32 images, with about 1,500 starting images and a cap of 10,000; those details come from participants' write-ups, not an official page.

Part 2 · covers the spec

Write the edit down so it outlives the model

5 min live

A data-edit spec is one page with seven fields. Each field answers a question somebody will ask six months from now, usually when a new model arrives or a number looks too good. Which model was frozen, and how? Which test file, and was it ever touched? Which version of the label rule? Which detector, with which settings? Which rows changed, from what to what, and who said so? What did it buy on both counters? And what does the result not prove?

ONE PAGE OF FIELDS, TWO JOBS: SOMEONE AUDITS IT, SOMEONE RERUNS IT 1 · Freeze list kNN, k = 10, squared distance, seed 20210921 2 · Test-set rule never edited, never used to choose an edit 3 · Label guideline version the rule the labels follow, from session 2 4 · Detector and its settings 4 folds, out of sample, per-class thresholds 5 · Edit log, one line per row row, old, new, votes, reviewer 6 · Result table measured and planted counters, side by side 7 · What not to claim no win built on one or two digits, one seed Audit draw 20 flags at random and check each one by hand 17 of 20 real: about 85% row 5, given 1 Rerun someone who did not build it rebuilds the rows from the log on the frozen model, same seed must print 483 of 500 again Every field answers a question someone will ask later: which model, which test file, which rule, which rows, who said so.
🔍 Click to zoom - the form is not paperwork: two of its fields feed an audit, three feed a rerun, and the edit log feeds both
LiveThe edit log: one line per touched row3 min▶

The edit log is the field the other six exist to make trustworthy. One line per row the edit touched: the row id, the old label, the new label or "removed", what the detector said and how strongly, who reviewed it, and which guideline version they reviewed it against. With that line, any single change can be questioned and reversed. Without it, the only way to undo a bad cleaning pass is to throw the whole dataset away.

Here is a constructed sample, four lines long. The rows, labels and votes are real outputs of the session 3 detector on the 800 training digits; the reviewer column and the decisions on the two false alarms are constructed to show what a reviewed log looks like.

RowOldNewDetector votes (of 10)ReviewerGuideline
5178 for 7, 2 for 1R1: confirmed, it has a top barv2
25717 for 1, 3 for 7R1: confirmed, single strokev2
0837 for 3, 3 for 8R2: confirmed, open on the leftv2
6333 (kept)7 for 8, 3 for 3R2: false alarm, label standsv2

Row 63 is the one that matters. The detector suggested 8; the digit is a 3. On the bench, the 13 false alarms among the 98 flags were all relabelled wrongly, because nobody reviewed them. A reviewer column is what turns a detector's suggestion into a decision.

LiveThe freeze list, and the rest of the form2 min▶

Freeze list. The model and every setting that decides its output: kNN, k = 10, squared Euclidean distance on 64 integer pixels, distance ties to the earlier training row, vote ties to the nearest tied neighbour, seed 20210921, no preprocessing, accuracy as the metric, and a checksum of the test file so anyone can prove it is the same 500 digits.

Test-set rule. Never edited, never used for decisions. The MIT notes: evaluation examples "should only be used for computing evaluation scores, not for any modeling decisions."

Guideline version from session 2, detector and settings from session 3 (four folds, per-class thresholds, out of sample), result table with both counters from session 4, and what not to claim: no one-seed, one-digit wins; no precision or recall quoted from a declared plant as if it were the real noise.

Ng's closing checklist makes a good acceptance test for the finished page. Good data is "defined consistently", has "cover of important cases", has "timely feedback from production data", and is "sized appropriately". The guideline field answers the first, the slice work of session 5 the second, the result table the fourth. The third is production monitoring, and Data Observability ↗ owns it.

Self-studyVersioning the dataset like code3 min▶

A spec is only as good as its link to the exact rows it describes. The simplest working pattern: keep the raw labels read-only, store the edit log as a small table next to them, and build the training set by applying the log to the raw labels. Then the dataset version is the log's version, a diff between two versions is a diff between two logs, and a reviewer can read a change the way they read a pull request.

Three habits make it hold up. Give the edit log a version that moves with the guideline version, so a rule change forces a new log. Record the detector settings in the log header, so a rerun cannot silently use different folds. And never overwrite a label in place: an overwritten label is a change with no author and no reason.

Real world

Three transcripts of the same sentence. Ng's example of inconsistent labels is speech: one labeller writes "Um, today's weather", another "Um... today's weather", a third "Today's weather". None is wrong; the instruction left room. The fix is a guideline version, and the reason the spec records it is that a relabelled row is only correct relative to a rule. Change the rule and the same row can become an error again.

Part 3 · covers auditing without an answer key and stopping

Audit a sample, then stop on a rule

5 min live

At work there is no declared plant. Nobody can tell you the detector's precision is 86.7 percent, because nobody knows which labels are wrong. What you can do is draw a random sample of the flags and check them by hand. That estimate goes on the spec, with its sample size. Then a second question: once the first pass is done, is another pass worth it? The answer is a rule written before the pass, not a feeling after it.

EACH PASS FINDS LESS: THE SECOND ONE IS THE SIGNAL TO STOP same frozen model, same 500 test digits · planted counts exist only because the plant is declared ROWS FLAGGED WRONG LABELS LEFT TEST DIGITS CORRECT OF 500 98 6 pass 1 pass 2 85 real errors 5 still wrong 133 61 57 start pass 1 pass 2 478 479 pass 1 pass 2 +1 digit = 0.2 points inside the noise on one seed Pass 2 reran the same detector on the relabelled 800. It found 5 of the 61 wrong labels still there, and missed the other 56.
🔍 Click to zoom - pass 1 moved 72 wrong labels, pass 2 moved four and one test digit; the detector has run out of what it can see
LiveEstimate precision by hand-checking a random sample3 min▶

Northcutt, Athalye and Mueller had exactly this problem on ten public test sets: an algorithm flagged candidates, and nobody knew which were real. Their design is the one to copy. Each flagged item went to five crowd workers on Mechanical Turk, and it counted as a label error if fewer than 3 of the 5 agreed with the given label. Across the ten datasets, 51 percent of the flagged candidates were confirmed on average, and the spread was wide: on MNIST, only 15 of 100 flags were real errors. Precision is a property of the detector on this data, not of the method.

The build-along runs the small version. From the 98 flags, a random sample of 20 with seed 6: 17 were real errors, an estimate of 85 percent. On the bench we can compare it with the true precision, 86.7 percent, because the plant is declared. At work you only have the 85. With 20 items the estimate is rough: one more or one fewer real error moves it by 5 points. Write the sample size next to the number on the spec, and check a larger sample before a precision figure decides anything expensive.

LiveThe stopping rule2 min▶

Run the same detector a second time on the relabelled 800. It flags 6 rows, and 5 of them are labels that are still wrong. That sounds efficient until you look at the denominator: 61 wrong labels were left after pass 1, so pass 2 finds 5 of them and misses 56. Test accuracy moves from 478 to 479, one digit, noise. Wrong labels fall from 61 to 57.

The rule: stop when a pass flags few rows and the audited precision of its flags falls, and move the effort to where the remaining errors actually come from. The 56 the detector cannot see are the look-alikes that sit deep in the other digit's neighbourhood; no amount of re-running finds them. They are a guideline problem (session 2) or a coverage problem (session 5). Write the thresholds down before the pass starts. A constructed example: "stop when a pass flags fewer than 10 percent of the previous pass's rows, or when a 20-flag audit finds fewer than half real."

Self-studyWhy the audit has to be random2 min▶

It is tempting to review the top of the list, the flags the detector is most confident about. Those are the easiest ones, and their precision is higher than the rest. An audit of the top 20 estimates the precision of the top 20, and the spec would quote it for all 98. A random draw from all the flags, with the seed recorded, estimates the precision of the whole pass, and anyone can redraw the same sample to check the reviewer.

The same logic sets who reviews. The labelerrors.com design used five independent workers and a 3-of-5 rule so that one tired reviewer could not decide an item. For a small internal audit, two reviewers who disagree on a flag is itself a finding: the guideline has a hole there.

Real world

A model ranking that flips on corrected labels. On ImageNet with corrected test labels, ResNet-18 outperforms ResNet-50 if the share of originally mislabelled test examples rises by just 6 percent; on CIFAR-10, VGG-11 outperforms VGG-19 at 5 percent. A result table built on an unaudited test set can pick the wrong model. That is why the spec's test-set field records who checked it, and why the audit design comes from the paper that found the flip.

What to ask for, if you lead the team. Three things, before the cleaning starts, not after. The one-page spec, filled, so someone else could rerun it. The audited precision of the detector with its sample size, "17 of 20", never a bare percentage. And the stopping rule, written in numbers before the next pass, so that "one more pass" is a decision the page makes and not a mood the team is in.

Build-along

Beat it, audit it, write it down

★ 22 min · everyone builds

Four steps. The first is on the session 4 bench in your browser; the next two continue from session 3's script in numpy, steps 1 to 5, with its variables still in memory; the last is a page of plain text. Every number printed below is what the code produces.

THE CAPSTONE LOOP: THE SPEC IS WHAT SURVIVES TO THE NEXT MODEL 1 · Bench knobs 1,297 rows + relabel + drop ambiguous 2 · Result table 483 of 500, 96.6% 58 wrong labels left 3 · Audit 17 of 20 flags real second pass: 6 flags 4 · The spec one page, filled 5 · The next model swap the model, keep the spec rerun the log, compare the spec outlives the model same spec, new rows Steps 1 to 4 are tonight. Step 5 is the day a new model arrives and nobody has to reverse-engineer the data.
🔍 Click to zoom - knobs make the number, the audit tests it, the spec keeps it; the dashed arrow is the reason to write it at all

Beat 96.0 on the bench, and record every readout. Open the session 4 bench, go below the eight presets to the knobs, and look for a combination above the best 800-row preset. Add the 497 extra rows, relabel the flags, drop the ambiguous rows, keep the detector out of sample. The readout prints 96.6 percent. Write down all eight numbers, not just the headline: the spec needs the cost as well as the gain.

★ Step 1 · the eight readouts, copied from the benchknobs: 1,297 rows, relabel flags, drop ambiguous, no shift, out of sample Test accuracy 96.6% measured Correct 483 of 500 clean test digits Against the baseline +5.2 points (baseline 91.4%, true labels 97.8%) Training rows 1,154 measured Ambiguous dropped 143 Wrong labels left 58 of 219 planted in these rows planted Detector precision 88.0% 117 of 133 flags were planted errors Detector recall 53.4% 117 of 219 planted errors found tie: 1,297 + remove + drop ambiguous + shift also prints 483, on 1,357 rows

Audit a random sample of 20 flags. Back in Python, on the 800. Draw 20 of the 98 flags with a recorded seed and check each one. On the bench the true digit stands in for the human reviewer; at work this line is a person with the guideline open.

★ Step 2 · audit 20 flags# continues from session 3's script, steps 1 to 5 # (X, y, train, g_train, Xtr, folds, knn_votes, confident_joint, flag, sug, score) audit_rng = np.random.default_rng(6) flagged = np.where(flag)[0] sample = audit_rng.choice(flagged, 20, replace=False) really_wrong = int((g_train[sample] != y[train][sample]).sum()) # stands in for a human reviewer print("audit:", really_wrong, "of 20 sampled flags were real errors") # audit: 17 of 20 sampled flags were real errors

Run a second pass, and read it against the stopping rule. Take the relabelled labels as the new given labels, recompute the out-of-sample votes with the same four folds, and run confident learning again. Count what it flags, how many of those are still wrong, and what it does to the test score.

★ Step 3 · the second passlab = sug.copy() planted_now = lab != y[train] V2 = np.zeros((800, 10), dtype=int) for f in range(4): hold = folds == f V2[hold] = knn_votes(Xtr[~hold], lab[~hold], Xtr[hold]) _, sug2 = confident_joint(V2, lab) flag2 = sug2 != lab tp2 = int((flag2 & planted_now).sum()) print("pass 2: flagged", int(flag2.sum()), "of which still-wrong labels", tp2, "| wrong labels before pass 2:", int(planted_now.sum())) # pass 2: flagged 6 of which still-wrong labels 5 | wrong labels before pass 2: 61 print("pass 1:", score(Xtr, lab), "| pass 2:", score(Xtr, sug2), "of 500") # pass 1: 478 | pass 2: 479 of 500 print("wrong labels after pass 2:", int((sug2 != y[train]).sum())) # wrong labels after pass 2: 57

Write the spec. One page, plain text, in the repository next to the data. The settings below are the real ones from these six sessions; the guideline version, reviewer names, file names and the stopping thresholds are a constructed example of how to fill the fields. Leave the checksum as a field until you compute it on your own test file.

★ Step 4 · the one-page data-edit specDATA-EDIT SPEC · digits · v1 (constructed example on real settings) 1. FREEZE LIST model kNN, k = 10, squared Euclidean on 64 integer pixels tie rules distance ties to the earlier row; vote ties to the nearest tied neighbour seed 20210921 (split and plant) preprocess none, raw pixels 0 to 16 metric accuracy on the 500 test digits test file sha256 of the test ids: <fill in> 2. TEST-SET RULE never relabelled, never filtered, never used to choose an edit 3. LABEL GUIDELINE version v2: adds the 1/7 rule from session 2 4. DETECTOR confident learning, 4 folds, out-of-sample votes, per-class thresholds thresholds as printed: 1.00 0.49 0.94 0.54 0.59 0.95 0.98 0.66 0.58 0.60 5. EDIT LOG file edits_v1.csv, one line per touched row: row, old label, new label or removed, votes, reviewer, guideline version 6. RESULT TABLE (same frozen model, same 500 test digits) baseline, 800 rows 457 91.4% 800 rows 133 wrong left relabel + shift, 800 480 96.0% 1,084 rows 61 wrong left 1,297 + relabel + drop ambiguous 483 96.6% 1,154 rows 58 wrong left twenty-seed means: relabel 94.45, relabel + shift 94.52, collect + clean 94.60 7. AUDIT AND STOPPING RULE audit: 20 random flags, seed 6, 17 real (about 85%, rough at n = 20) stop when a pass flags under 10% of the previous pass's rows (constructed) pass 2 flagged 6 of 98: stopped; next effort goes to the guideline 8. WHAT NOT TO CLAIM no win from a difference of one or two test digits on one seed precision and recall exist here only because the plant is declared the 96.6 result is one seed; the twenty-seed sweep did not run it
Same frozen model, same 500 test digitsTraining rowsCorrectAccuracy
The labels you were given80045791.4%
Relabel the flags, one pass80047895.6%
Relabel, then a second pass80047995.8%
Best on the 800 alone: relabel + shift the weakest digit1,08448096.0%
Best overall: 1,297 rows, relabel, drop ambiguous1,15448396.6%
The true labels (knowable only because the plant is declared)80048997.8%

Read the audit and the second pass together. The audit says the first pass was mostly right: about 85 percent of its flags were real, on a sample of 20. The second pass says it was also mostly done: 6 flags, one test digit. A detector that is accurate and exhausted is the moment to stop running it and start reading the 56 errors it cannot see.

Homework

After the capstone

60 min
  1. Write the spec for your own dataset. All seven fields plus the audit and stopping rule, one page. Leave a field visibly empty rather than guessing; an empty field is a to-do, a guessed one is a future argument.
  2. Run a 20-flag audit. Draw 20 flags from your detector at random, with a recorded seed, and have them checked by someone holding the guideline. Write the result as "k of 20", not a percentage.
  3. Set your stopping rule in numbers before the next pass. How few flags, and how low an audited precision, ends the cleaning? Write it on the spec, then run the pass.
  4. Hand the spec to someone who did not build it and ask them to rerun it. Every question they ask is a missing field. Every number they cannot reproduce is a missing line in the freeze list.
Check yourself

Three questions

Clear all three and session 6 gets stamped in your passport.

1 · On the shipped seed, one combination of edits scores 483 of 500 and another scores 482. What do you conclude?

The sweep shows how small real differences are: relabel, relabel plus shift and collect plus clean average 94.45, 94.52 and 94.60, all within one test digit. A single-seed, single-digit gap is below what this test set can measure. D breaks the test-set rule outright.

2 · At work there is no declared plant. How do you estimate your detector's precision?

Northcutt, Athalye and Mueller checked every flag with five workers and a 3-of-5 rule, and found precision ranging from 15 of 100 on MNIST to much higher elsewhere: it depends on the data, so neither the bench's number nor the study's average transfers. A top-20 review measures only the easiest flags.

3 · A second detector pass flags 6 rows, and test accuracy moves from 478 to 479. What should the team do?

Pass 1 moved 72 wrong labels; pass 2 moved four and one test digit. The stopping rule, written before the pass, says a pass this small ends the cleaning. C is session 3's leak: 95.2 percent precise and only 30.1 percent recall, because each row votes for itself.

Sources covered

What this session teaches, and where it came from

◐Data-Centric AI Competition (2021)The format, a dataset improved for a fixed model and scored on accuracy, and the 4 September 2021 deadline read at source; model, image size and caps reported from participant write-ups
✓Ng, "MLOps: From Model-centric to Data-centric AI" (2021)The four properties of good data used as the spec's acceptance checklist, and the speech-transcription example, read from the slide deck
✓Northcutt, Athalye, Mueller (2021), label errors in test setsThe five-worker, 3-of-5 audit design, the 51 percent average confirmation, 15 of 100 on MNIST, and the ResNet-18 against ResNet-50 flip, read from the NeurIPS paper
✓MIT, Introduction to Data-Centric AI (2023, 2024)The rule that evaluation examples are only for computing scores, never for modelling decisions, read from the lecture notes
✓Every bench and build-along numberComputed on the UCI Optical Recognition of Handwritten Digits (Alpaydin and Kaynak, 1998); the noise plant, the sample edit log and the filled spec are constructed and say so

Every fact on this page, and its verification tier, is recorded in the course's source map.

Session 6 cheat sheet · pin this

Only the data movesModel, seed and test set frozen; every edit logged. 96.6 on the bench, from edits alone.
One digit is 0.2 pointsA one-digit, one-seed gap is not a win. Judge against multi-seed means.
Seven fields, one pageFreeze list, test-set rule, guideline version, detector, edit log, result table, what not to claim.
The edit logRow, old, new or removed, detector votes, reviewer, guideline version. Never overwrite in place.
Audit at randomSample flags with a seed, check by hand, report "17 of 20" with the sample size.
Stop on a ruleWritten before the pass. A second pass of 6 flags and one digit says: go fix the guideline or the slice.