Where we start
Session 1 froze a model and a test set and planted declared noise in 800 training labels. That noise came from one imaginary labeller. Real labelling teams have several people, a written guideline, and a queue of rows somebody argued about. Tonight the question moves one step upstream of "which rows are wrong": how consistent is the labelling in the first place, and when two people disagree, is the fix another person or a better rule?
★ What you walk out with tonight. Ng's two-labeller protocol, Cohen's kappa computed by hand, a per-class agreement table that points at the rule to rewrite, the proof that agreement is not correctness (670 rows agreed, 68 wrong together), and a costed comparison of majority vote against a guideline rewrite on the same frozen model.
Two careful people, two answers
5 min liveNg's 2021 talk spends several slides on one idea: much of what looks like label noise is not error at all, it is inconsistency. Three transcriptions of the same audio clip read "Um, today's weather", "Um... today's weather" and "Today's weather". None of them is wrong. The instruction never said what to do with a hesitation. A model trained on all three learns that the answer is a coin toss, and no amount of model work removes a coin toss that lives in the labels.
LiveThe protocol, in Ng's own words2 min▶
Ng's slide on making data quality systematic is three sentences long, and every word is doing work: "Ask two independent labelers to label a sample of images. Measure consistency between labelers to discover where they disagree. For classes where the labelers disagree, revise the labeling instructions until they become consistent."
Notice what it does not say. It does not say "find the bad labeller" or "take the majority". The unit of repair is the instruction, and the unit of measurement is the class. A sample is enough, because the goal is to find which parts of the rule are ambiguous, not to relabel the whole set twice. The iguana example on the same deck shows how little it takes: the instruction "Use bounding boxes to indicate the position of iguanas" produces boxes that differ from labeller to labeller, and every one of them follows the instruction.
LiveInconsistent is not the same as wrong2 min▶
An error is a label that contradicts the rule: a 3 labelled 8 when the guideline is clear that it is a 3. An inconsistency is two labels that each satisfy the rule, because the rule does not decide the case. You cannot call "Um... today's weather" wrong until someone has written down whether hesitations are transcribed and how. Before that, it is one of several defensible answers.
This matters for what you do next. Errors are fixed row by row, and session 3 builds a detector that finds them. Inconsistencies are fixed once, in the guideline, and then every affected row is relabelled against the new rule. Running an error detector on an inconsistent dataset flags rows whose label is "wrong" only relative to the model's guess at what the rule should have been.
Self-studyWhy this is a spec problem, not a people problem3 min▶
When two labellers disagree the tempting move is to rank them, retrain the weaker one or replace them. That treats the symptom. If two careful people read the same instruction and diverge, the instruction admits both readings, and a third careful person will diverge too, in a direction you cannot predict. Replacing people does not remove the ambiguity; it only changes which reading wins this month.
Treat the guideline the way an engineering team treats an API contract. It has a version number. Every class has a definition, a list of edge cases with a ruling for each, and examples of both sides of every boundary. A disagreement is a bug report against the contract. The fix is a new version, and rows labelled under the old version are marked so they can be rechecked. Session 6 writes that version into the data-edit spec, so the guideline outlives the team that wrote it.
People problems do exist. The careless labeller C in tonight's build-along is one. But you can only tell a careless person from an ambiguous rule once the rule is clear enough that careful people agree on it, which is why the rule comes first. The disputed rows themselves usually come out of error analysis, which ML Strategy p3 ↗ covers.
Steel class 23 of 39. Ng's steel inspection project has 39 defect classes, and the slide he uses for label consistency picks one: "Class 23: Foreign particle defect". It is one class in 39, and the slide uses it to show labels for the same kind of defect coming back inconsistent. The point of picking one class is the point of the protocol: the repair is not a better detector for class 23 but a sharper definition of what class 23 is, followed by relabelling against it.
Agreement beyond percent the same
6 min liveThe first number anyone computes is raw agreement: the share of rows where the two labels match. It is the right place to start and the wrong place to stop, because two people guessing at random would still agree some of the time. Cohen's kappa, from 1960, subtracts that chance agreement out: kappa = (p_o - p_e) / (1 - p_e), where p_o is the observed agreement and p_e is the agreement you would expect if each labeller kept their own label frequencies but assigned them independently of the image. Kappa of 1 is perfect agreement, 0 is no better than chance.
Tonight's numbers, from the build-along on the real 800 training images with constructed labellers. A is session 1's declared plant. B works from the same guideline and makes the same look-alike confusions, drawn independently. C is careless: a fifth of C's labels are replaced by a random digit.
| Pair | Raw agreement p_o | Chance p_e | Cohen's kappa |
|---|---|---|---|
| A and B (same guideline, same confusions) | 83.8% | 10.1% | 0.819 |
| A and C (C is careless) | 67.6% | 10.0% | 0.640 |
With ten nearly balanced classes, chance agreement is only about 10 percent, so kappa sits close to raw agreement. That is not always true, and the self-study card below says when it breaks.
LiveWhy kappa is not a quality score3 min▶
Look at the pair with the higher kappa. A and B agree on 670 of the 800 rows, and 68 of those 670 are wrong together: both labellers wrote the same wrong digit. That is not bad luck. They share a guideline, so they share its blind spots; a 7 without a clear top bar looks like a 1 to both of them for the same reason. Kappa compares the labellers with each other and never with the truth, so a shared confusion raises it.
So kappa measures consistency, and consistency is the thing Ng's protocol asks for, which makes it the right tool for finding ambiguous classes. It is the wrong tool for certifying a dataset. A high kappa on a class tells you the rule is being read the same way; it does not tell you the rule is right. For that you need either a ground truth sample checked by someone who knows the domain, or a detector that looks at the images, which is session 3.
The per-digit table points at where to start. Every disagreement between A and B falls on one of the three look-alike pairs:
| A's label | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|---|
| B agrees | 100% | 71% | 100% | 71% | 67% | 100% | 100% | 76% | 77% | 72% |
Self-studyKappa's own known limits3 min▶
Three limits are standard in the measurement literature, and each one shows up in real labelling projects.
Prevalence. Chance agreement p_e is computed from each labeller's label frequencies. When one class dominates, say most rows are "no defect", both labellers use that label most of the time, so p_e is high, and even a high raw agreement can produce a modest kappa. The same labelling quality gives different kappas on datasets with different class balance, so a kappa from one project does not transfer to another.
Few classes. With two classes, chance agreement is 50 percent when both labellers use the two labels equally often, and higher when one label dominates, so the gap between raw agreement and kappa is large. With ten balanced classes, as tonight, it is small. Compare kappas only between tasks with the same number of classes and similar balance.
It is one number for all classes. A kappa of 0.8 can hide one class at perfect agreement and another near chance. Always report the per-class table alongside it. Cohen's kappa is also defined for exactly two labellers; for more, extensions such as Fleiss' kappa exist, with the same caveats. Published verbal scales ("substantial", "almost perfect") are conventions, not measurements, so set your own threshold per class from what a disagreement costs.
Systematic, not random. When Northcutt, Athalye and Mueller had crowd workers check the label errors in ten benchmark test sets, they found the errors were "primarily systematic mislabeling, not just random noise". Systematic errors are exactly the kind two labellers share, which is why a benchmark can have good inter-annotator agreement and still carry thousands of wrong labels.
Three labels, one answer
6 min liveWhen each row carries more than one label, something has to turn them into one. The default is majority vote, and the MIT data-centric AI notes on dataset creation name its two flaws in two lines: "Resolving ties is ambiguous in majority vote", and "A bad annotator and good annotator have equal impact". Everything more sophisticated exists to fix one of those two sentences.
LiveMajority vote, and the two sentences that break it2 min▶
Tonight's three constructed labellers vote on each of the 800 rows. The majority label is right on 89.8 percent of them, and it leaves 82 wrong labels against 133 for A alone. Trained on the vote, the frozen model scores 483 of 500, against 457 on A's labels. That is a real gain, and it costs three labels on every row.
Both flaws show up in the same run. On 25 rows all three labellers wrote a different digit, a three-way split with no majority; the build-along falls back to A's label and says so, which is a choice, not a rule. And C, who guesses on a fifth of rows, gets exactly the same vote as A and B. Where A and B share a confusion, C's occasional correct answer is outvoted two to one, which is how the 68 rows wrong together survive the vote.
LiveWeighting annotators: Dawid-Skene and CROWDLAB2 min▶
The MIT notes describe the step beyond the vote. First, estimate each annotator's quality as their agreement with the consensus, then let better annotators count for more. The classic model for this is Dawid-Skene, which learns a full confusion matrix per annotator: not just "C is wrong 20 percent of the time" but "B writes 1 when the truth is 7". The notes also give its limit: it cannot give a reliable consensus for rows labelled by only one annotator, which in practice is most rows of most datasets.
CROWDLAB closes that gap by adding a model. It combines any classifier's predicted probabilities with the annotations, so a singly labelled row still gets a second opinion from the model, and multiply labelled rows get the annotators weighted by how reliable they have proved. Neither is computed here; both are named so you recognise them when a vendor quotes them. Note what neither can do: if every annotator shares the same confusion, weighting them differently does not recover the truth.
Self-studyRewrite the rule, or add a labeller?3 min▶
The build-along runs a constructed experiment: suppose a revised rule, "a 7 has a top bar, a 1 is a single stroke", ends the 1 and 7 confusion and nothing else. It fixes 48 rows of A's labels, and the frozen model goes from 457 to 472. The vote got to 483, higher, but it paid for two more complete passes over all 800 rows. The rule fixed one of three confused pairs with one rewrite and a recheck of the 1s and 7s; rules for 3/8 and 4/9 are the obvious next edits. The effect of the rule is constructed, the images and the model scores are real.
Sheng, Provost and Ipeirotis (2008), "Get Another Label?", study when repeated labelling improves label quality and model quality. As reported from the paper's abstract, the answer is that it pays under conditions rather than always; read the paper before budgeting a second or third pass. The order that follows from tonight is Ng's: measure agreement on a sample, rewrite the rule where it breaks, and pay for extra labels only on the classes that stay inconsistent after the rewrite.
Five workers, three must agree. The labelerrors.com study used consensus as a verification step rather than a labelling step. Each item flagged by the algorithm was shown to five Mechanical Turk workers, and it counted as a label error if fewer than 3 of the 5 agreed with the given label. Consensus was spent only on the rows a detector had already flagged, which is where it buys the most, and the authors still note the corrected labels "are not 100% perfect".
What to ask for, if you lead the team. Before paying for a second labelling pass, ask for two things: the agreement matrix per class from two independent labellers on a sample, and the version number of the guideline they worked from. If the disagreement sits in a few classes, the next spend is a rule rewrite for those classes, not another pass over every row.
Three labellers, one vote, one better rule
★ 22 min · everyone buildsSix steps in numpy on the same 800 real training images as session 1. The three labellers are constructed and declared, so every accuracy figure can be checked against the true digit. Every number printed below is what the code produces.
Three labellers on the same 800 images. This continues from session 1's steps 1 to 4, which define X, y, train, test, PLANT, centre, g_train and score; run those first. Labeller A is session 1's declared plant. B reads the same guideline and makes the same look-alike confusions, drawn with its own seed. C is careless: a fifth of C's labels are replaced by a random digit. All three are constructed; the images are real.
Raw agreement, chance agreement and kappa. Chance agreement is the sum over digits of the product of the two labellers' label frequencies: how often they would match if each kept their own habits but ignored the image. Kappa is the share of the remaining room that they actually closed.
Find where they disagree, class by class. Group the rows by A's label and ask how often B wrote the same thing. This is the table Ng's protocol runs on: the classes below 100 percent are the ones whose rule needs rewriting.
Check agreement against the truth. This step is only possible because the labellers are constructed and the true digits are known. On your own data you would need a checked sample. Count the rows where A and B agree, and how many of those they got wrong together.
Take the majority vote, and handle the ties out loud. Where all three labellers wrote a different digit there is no majority. The code falls back to A and counts how often that happens, so the choice is visible in the output instead of buried in an argmax.
Rewrite the rule for the worst pair, then score everything on the frozen model. The rewrite is a constructed effect: we suppose the new rule "a 7 has a top bar, a 1 is a single stroke" ends the 1 and 7 confusion and touches nothing else. Then the same frozen kNN from session 1 is trained on three label sets and scored on the same 500 untouched test digits.
| Same frozen model, same 500 test digits | Labels per row | Wrong training labels | Correct |
|---|---|---|---|
| Labeller A alone (the declared plant) | 1 | 133 | 457 |
| A with the 1/7 rule rewritten (constructed effect) | 1, plus a recheck of one pair | 85 | 472 |
| Majority vote of A, B and C | 3 | 82 | 483 |
Read the middle row as a first step, not a final answer. One rule for one of three confused pairs bought 15 test digits for a fraction of the labelling cost the vote needed for 26. The same rewrite for 3/8 and 4/9 is the next edit, and the vote still carries the 68 rows A and B got wrong together, which only a rule change or a detector can reach. On one seed a difference of a digit or two is noise, one test digit being 0.2 points; the gaps here are large enough to read, but not to rank the two routes to the decimal.
Before session 3
30 min- Compute kappa for two real people. Take 50 rows of your own data, have two colleagues label them independently from the current guideline, and run step 2's kappa function on their two columns. Write down raw agreement, chance agreement and kappa.
- Find the class with the lowest agreement using step 3, and write its rule: a definition, the edge cases with a ruling for each, and one example on each side of every boundary it shares with a neighbour class.
- Price the two routes. Estimate the cost of a third label on every row against the cost of the rule rewrite plus a recheck of the affected classes. Which would you fund first, and what agreement number would make you change your mind?
- Bring your team's flagged rows list. Session 3 finds wrong labels with a detector; a list of rows your team already suspects is the best way to see what it catches and what it misses.
Three questions
Clear all three and session 2 gets stamped in your passport.
1 · Labellers A and B have a Cohen's kappa of 0.819, yet 68 of the 670 rows they agree on are wrong together. What does kappa measure?
Kappa is a consistency measure, which is exactly what Ng's protocol needs for finding ambiguous classes. It cannot certify correctness: two labellers trained on the same guideline share its blind spots, and their shared wrong labels count as agreement.
2 · Three labellers vote, and one of them guesses at random on a fifth of the rows. Why do methods such as Dawid-Skene and CROWDLAB weight annotators instead of counting votes?
The MIT notes name both flaws: ties are ambiguous and every annotator counts the same. Tonight's vote had 25 three-way splits and fell back to A on each. Weighting fixes the equal-impact flaw, but no weighting recovers the truth when every annotator shares the same confusion.
3 · Your two labellers agree above 95 percent on every class except two look-alike classes, where they sit near 70 percent. Following Ng's protocol, what is the next move?
Ng's slide: "For classes where the labelers disagree, revise the labeling instructions until they become consistent." Disagreement concentrated in a few classes is a spec problem. Tonight the rule rewrite for one pair bought 457 to 472 with one rewrite; the vote bought 483 but cost three labels on every row.
What this session teaches, and where it came from
Every fact on this page, and its verification tier, is recorded in the course's source map.
Session 2 cheat sheet · pin this
With a clear rule, a label that breaks it is simply wrong, and the job becomes finding those rows without reading all 800. Session 3 builds confident learning by hand: out-of-sample probabilities, a threshold per class, and a grid of counts that says which given labels the model confidently disagrees with. Bring your team's flagged rows list.