Chapter 5 · Applied Natural Language Processing
SKIP optionsentimentEach table says which components stay fixed, so a change in score is interpreted only inside the controlled comparison of its own table.
| what was observed | the scope it holds in |
|---|---|
| A 2% error rate in the test labels takes the top entry from 76.21 down to 73.13 — below the 73.51 its bag-of-words rival scored on the original labels | Two conditions with differently labelled test sets, not a rank reversal on a shared one. On the same noisy labels the 2.69-point gap shrinks to 2.50 on average, and the order changes in none of 200 draws |
| Of the 40 selected test reviews the model disputed most strongly, 20 were classified as texts that a single binary label struggles to describe | One reader, a selected sample: the proportion cannot be carried over to the dataset as a whole |
| 1,000 clean labels tie with 40,000 labels at 10% noise; at 20% noise 500 clean labels are ahead of all 40,000 | Artificial noise on one model and one corpus; the tie and the lead were each checked with ten seeds |
Not because the model changed, but because the labels the score is computed against did.
Labels do not arise by themselves. At each step the meaning of the label can drift from what you assume.
| step | what happens there | what can break |
|---|---|---|
| raw text | scraped or logged | selection — who writes reviews is not who buys (93.7% positive) |
| schema | what the classes are | schema gap — texts the classes cannot express (20 of 40 read) |
| guideline | how to decide | ambiguity — the guideline is silent here (human–human κ not measured here) |
| annotator | reads, presses a key | clear label error — possibly fatigue, misreading, a slip (11 of 40 read) |
| stored label | one column | collapse — disagreement is not recorded (1 column left) |
The 20/40 and 11/40 belong only to the single-reader audit of the 40 test reviews the model disputed most strongly; how often the problems at the other stages occur was not measured in this chapter.
| question | what to look at |
|---|---|
| Who produced the text? | Not “the internet”: which platform, which population, which time window. People who chose to write a review are not the people who bought |
| Who produced the labels, and how? | Domain experts, crowdworkers, a model, or the platform’s star rating. A sentiment class derived from stars is a proxy labelling decision |
| What question were they answering? | “Is this review positive?”, “Would you buy this product?” and “Is this customer satisfied?” produce different labels on the same text |
| What licence, and does it cover your use? | Research-only is a real restriction. So is a licence that permits redistribution of the text but not of derived models |
| What legal basis and what notice existed? | That anyone can read a review does not show that explicit consent to model training was given |
| What is missing? | Which texts were deleted, filtered, or never written, and which groups does that affect? |
Record what the source does not say as “undocumented”, and assess separately what that uncertainty means for your decision to use the data.
Longpre et al. 2024
100 of the 10,000 test rows, drawn with seed 42 and read with the label visible. Criteria fixed before reading: error, undecidable, ok.
arguable was split off from ok during the reading — a deviation from the scheme fixed in advance, so a post-hoc category that carries less weightTest row 4745, in full: sipariş verdim umarım tez ulaşır :) — “I placed the order, hope it arrives fast :)”. Gold label: positive.
sentiment label answered is not documented, so we do not call the source label of this row an errorThe problem may lie in the definition of the target question rather than in a wrong decision by the annotator. Hold onto this distinction between a label error and a schema problem.
A screening rule: mark ama, fakat, ancak and lakin — all roughly “but”. It matched in 2,003 of the 10,000 test reviews (20.03%).
| contrast rule matches | no match | |
|---|---|---|
| share of test set | 20.03% | 79.97% |
| gold negative rate | 11.48% | 5.03% |
| model accuracy | 84.07 | 94.70 |
| model macro-F1 | 72.11 | 77.72 |
| model F1 (negative) | 53.84 | 58.27 |
What the two situations share: a label can reflect the labelling process as well as the text.
### annotation guideline v1 — product review sentiment
TASK
Label each review positive (1) or negative (0) according to the
reviewer's verdict ON THE PRODUCT.
DECIDED CASES (these make the definition above concrete)
1. Delivery, packaging, seller, and returns are NOT the product.
"Fast shipping, product is useless" -> 0
"Shipping was late, the product is great" -> 1
2. Price complaints are NOT negative unless the reviewer says the
product is not worth it.
"Expensive but excellent" -> 1
"Not worth this money" -> 0SKIP option, kept together with a version number 3. Mixed verdicts on the product: the FINAL clause wins.
"Cuts well but the handle broke" -> 0
"The handle is cheap but it cuts very well" -> 1
4. Not yet received / no verdict given -> SKIP (do not label)
5. Truncated text: if the visible text contains a verdict, label it;
otherwise SKIP.
6. Judge negation in context. "fena değil" (not bad) is positive
for the product. "fena değil ama çabuk bozuldu" (not bad but it
broke quickly) is 0 by rule 3, because the final verdict on the
product is negative.SKIP exists: forcing a binary choice on undecidable items can manufacture disagreement — or an agreement that looks high and means littleNo second human annotator was available. A is the reference sentiment column; B is a lexicon rule — 36 positive and 37 negative phrases — applied to all 10,000 test rows.
\[\kappa = \frac{p_o - p_e}{1 - p_e} = \frac{0.9342 - 0.9099}{1 - 0.9099} = \mathbf{0.2698}\]
Cohen 1960
All 632 reviews A calls negative, plus a random 632 of the reviews A calls positive: a 1,264-row artificially balanced subsample.
Feinstein & Cicchetti 1990 · Cicchetti & Feinstein 1990
Report the number and the interval; treat the adjective as a label for a conversation, never as a passing grade.
Fleiss 1971 · Krippendorff 2018 · Landis & Koch 1977
Agreement measurement is diagnostic; adjudication is the step that follows it. Do not treat step 3 as a vote.
| sample | standard error of kappa | what follows |
|---|---|---|
| 10,000 items | about 0.02 | — |
| a plain random 200 | about 0.14 | the 95% interval around 0.27 is roughly \([-0.02, 0.54]\) |
| stratified: 100 gold-negative plus 100 gold-positive | about 0.04 | the point estimate moves to around 0.21 |
These numbers come from resampling the reference-versus-lexicon table; in your own pilot with two humans, compute the interval separately.
How you reduce several judgements to one label is a choice, and keeping the raw judgements lets you change that choice later.
Dawid & Skene 1979 · Uma et al. 2021 · Plank 2022
Reading all 40,000 rows by hand is expensive. Set up a procedure that chooses which rows to read first.
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
oof = np.zeros(len(y))
for train_idx, val_idx in skf.split(Xtr, y):
m = clf().fit(Xtr[train_idx], y[train_idx])
oof[val_idx] = m.predict_proba(Xtr[val_idx])[:, 1]
# the score the model gives to the opposite class;
# not the probability that the label is wrong
wrong_conf = np.where(y == 1, 1 - oof, oof)Northcutt et al. 2021
| threshold | rows flagged | share | gold positive | gold negative |
|---|---|---|---|---|
| > 0.50 | 3,026 | 7.57% | 2,232 | 794 |
| > 0.90 | 92 | 0.23% | 49 | 43 |
| > 0.95 | 34 | 0.09% | 18 | 16 |
| > 0.99 | 2 | 0.005% | 2 | 0 |
With the vectoriser also fitted inside each fold, the 92 rows above 0.90 become 123 and the 34 above 0.95 become 47; 89 of the first 92 candidates are in the new list too. What follows belongs to the first list of 92.
A separate audit, on the test set: the 40 reviews on which the model disputed the stored label with the highest score.
### 40 highest-confidence gold/model disagreements, test set, read by hand
error (gold label is wrong) 11 27.5%
schema (binary label cannot represent the text) 20 50.0%
model (label defensible, classifier wrong) 9 22.5%
--
data-side problems 31 / 40
schema breakdown: mixed 12 · truncated 4 · lukewarm 3 · no verdict 1| row | gold | what the text says | how it was read |
|---|---|---|---|
| 6874 | negative | clear praise, no visible reservation; model p(positive) = 0.984 | plainly contradicts the negative label |
| 8356 | positive | “yastıklar ince yeterli değil” — “the pillows are thin, not enough”; p = 0.059 | another clear contradiction |
| 8006 | positive | praises the returns process and reports “I did not like it” as the reason for the return; p = 0.034 | counted as a model error; under guideline v1 the label would be 0, or the row SKIP |
| 2544 | positive | “paketleme başarısız. ampüller fena değil” — “packaging failed. the bulbs are not bad” | two verdicts of opposite polarity about two different aspects |
The category depends on the definition of the target: read the counts as a direction rather than a rate.
### repairs, judged on the test split used throughout the chapter
acc macro-F1 F1(neg)
baseline (no repair) 92.57 76.21 56.47
drop 92 (p > 0.90) 92.37 75.72 55.61
flip 92 (p > 0.90) 92.47 75.94 55.99
drop 34 (p > 0.95) 92.39 75.83 55.83
flip 34 (p > 0.95) 92.52 76.03 56.15
drop 2 (p > 0.99) 92.54 76.15 56.37
flip 2 (p > 0.99) 92.52 76.11 56.31None of these six repair conditions beat the baseline on the test split used. The largest difference is about half a macro-F1 point (dropping the 92 rows: −0.49).
92 random rows with the same class mix as the 92 flags (49 positive, 43 negative), 20 separate draws.
Producing a review list and raising the score by dropping or flipping that list wholesale are separate goals. A flag is a reading list, not a decision.
Training labels corrupted at controlled rates, the model retrained, scored on the original test labels. Rates are shares of the source class; “symmetric” flips that share of each class.
| condition | rows flipped | the class afterwards | macro-F1 |
|---|---|---|---|
| neg → pos at 10% | 253 of 2,529 negatives | the positive class grows to 37,724, of which 253 are wrong: 0.67% contamination; the negative class shrinks to 2,276, every member correct | 76.42 |
| pos → neg at 10% | 3,747 of 37,471 positives | the negative class is 2,529 correct plus 3,747 wrong: 59.7% mislabelled | 63.63 (−12.58) |
| pos → neg at 1% | 375 rows, 0.94% of all training rows | 12.9% of everything now labelled negative (375 of 2,904) | 74.17 (−2.04) |
SKIP and to adjudicationMeasure your annotation error rate per class. Name the source class and the target class every time, and give the number of rows along with the percentage.
| labels flipped | neg → pos | pos → neg | share of the negative class | share of the positive class |
|---|---|---|---|---|
| 250 | 76.35 (sd 0.17) | 74.98 (sd 0.25) | 9.9% | 0.67% |
| 500 | 76.80 (sd 0.20) | 73.64 (sd 0.20) | 19.8% | 1.33% |
| 1,000 | 76.95 (sd 0.68) | 71.11 (sd 0.27) | 39.5% | 2.67% |
| 2,000 | 68.60 (sd 1.02) | 67.91 (sd 0.15) | 79.1% | 5.34% |
The flips were chosen independently of the text. Real errors can concentrate on hard items, and the effect of the same nominal rate then differs (Wei et al. 2022): do not read these numbers as a bound.
Now the reverse: one model, trained once on the original data, scored against test labels flipped in a controlled way.
### one fixed model, corrupted test labels, mean of 5 seeds
test noise acc macro-F1 F1(neg) sd(macro-F1)
### noise here = share of ALL test rows, flipped uniformly at random
0% 92.57 76.21 56.47 0.00
1% 91.73 74.68 53.90 0.23
2% 90.85 73.13 51.31 0.12
5% 88.31 69.41 45.36 0.17
10% 84.19 64.79 38.66 0.24
20% 75.48 57.00 28.82 0.36| system | macro-F1 |
|---|---|
| TF-IDF 1–2 gram, original test labels | 76.21 |
| TF-IDF 1–2 gram, 1% test-label noise | 74.68 |
| bag of words, original test labels | 73.51 |
| TF-IDF 1–2 gram, 2% test-label noise | 73.13 |
| TF-IDF unigram, original test labels | 71.95 |
| TF-IDF char_wb 3–5, original test labels | 70.39 |
Two percent artificial noise takes the same model from 76.21 to 73.13, below the 73.51 of bag of words on the original labels. Do not conclude that the ranking has reversed: the two are not compared on a common version of the labels.
“Which test set, with which labels” belongs in every comparison.
Set aside a separate quality budget for the test labels.
Recht et al. 2019 · Beyer et al. 2020
### split-before-dedup, the ordinary careless mistake
rows removed by exact de-duplication 1,657 (0.70%)
test rows also present in train 45 (0.45% of test)
near-duplicates after normalisation 34 (0.34% of test)
same model, same run:
accuracy on the 45 leaked rows 93.33
accuracy on the 9,955 clean rows 91.90
macro-F1 on the leaked rows 76.76
macro-F1 on the clean rows 74.08| test rows copied into train | accuracy | macro-F1 | F1 (negative) |
|---|---|---|---|
| 0% | 92.57 | 76.21 | 56.47 |
| 1% | 92.57 | 76.27 | 56.60 |
| 2% | 92.62 | 76.41 | 56.86 |
| 5% | 92.65 | 76.53 | 57.08 |
| 10% | 92.82 | 77.14 | 58.20 |
| 25% | 93.33 | 78.59 | 60.82 |
| 50% | 94.00 | 80.89 | 65.07 |
| 100% | 95.62 | 85.89 | 74.17 |
The 10% dose gives a difference of the size you would expect from a genuine modelling improvement. It is specific to this model, this dataset and this copying setup: not a fixed gain per 10%, nor an estimate of the effect of a natural leak.
| risk | the check |
|---|---|
| Exact duplicates across splits | Before splitting, group by the text; examine same-text, different-label conflicts first (77 groups in this corpus), then de-duplicate by a rule you have documented |
| Near-duplicates | Normalise case, punctuation and whitespace, then compare; for longer texts, Jaccard similarity over word n-gram “shingles”, or MinHash |
| Group leakage | The same user, the same document, the same patient: split on the group, not the row. This corpus has no reviewer identifiers; report that limitation |
| Temporal leakage | If your model will run on future data, your test set must be from the future |
| Preprocessing leakage | Fit the vectoriser, the scaler and the feature selector on the relevant training part only — inside every fold too (92 → 123 in this chapter’s audit) |
| Benchmark contamination | Public test texts may have entered the pretraining data of the pretrained model you are fine-tuning |
Kapoor & Narayanan 2023 · Magar & Schwartz 2022 · Oren et al. 2024
SKIP option and decided examples can keep an annotator from being forced into a binary decision on an ambiguous caseRecord in your datasheet who labelled, how they were paid and at what rate, stating the unknowns explicitly as well.
Gray & Suri 2019 · Sambasivan et al. 2021 · Gebru et al. 2021
The same model at seven budget sizes and six noise levels, three seeds each; all 42 cells are scored against the same original test labels.
### macro-F1 by budget and label noise (clean test set, 3 seeds)
0% 5% 10% 20% 30% 40%
500 59.44 58.56 55.57 51.18 47.40 42.12
1,000 63.71 60.91 57.77 52.32 46.99 42.78
2,500 68.76 64.17 60.03 53.36 48.23 42.93
5,000 71.69 66.00 60.21 53.17 47.86 42.42
10,000 73.72 66.47 61.81 54.46 48.53 42.88
20,000 74.89 66.99 62.04 55.21 49.09 43.81
40,000 76.21 68.18 63.20 55.74 49.34 44.16| pair | in the grid (3 seeds) | re-run with ten seeds each | reading |
|---|---|---|---|
| 1,000 clean labels against 40,000 labels at 10% noise | 63.71 against 63.20: a difference of 0.51 points | 62.24 (sd 2.24; 59.29–65.44) against 62.66 (sd 0.46) | a tie: the small clean set is ahead in 37 of the hundred seed pairs |
| 500 clean labels against 40,000 labels at 20% noise | 59.44 against 55.74 | a difference of 3.9 points | in the same direction in all hundred seed pairs |
The grid shows the balance of quality and quantity. The return per unit of money takes the costs of annotation and quality control, which have to be known separately.
Lowell et al. 2019
| method | what you do | what to watch |
|---|---|---|
| Weak supervision | write partial, noisy labelling functions and combine them; the lexicon rule in this chapter is one such source | dependence: five variations on the same keyword list should not count as five independent pieces of evidence |
| Distant supervision | use an existing signal as a proxy label: star ratings, a knowledge base, user clicks | the proxy is not the target: a 3-star review is not “neutral” |
| LLM labelling | prompt a large model to label your data | the model’s systematic biases; labels that may not be independent of a model you then evaluate |
These methods can reduce the need for human labels; they do not by themselves take the place of quality control. You still need a human-labelled test set to know whether any of it worked.
Ratner et al. 2017 · Gilardi et al. 2023 · Ziems et al. 2024 · Panickssery et al. 2024 · Pangakis et al. 2023
The main test set rests on real texts selected independently from the distribution of the target use. Synthetic examples can be used in additional stress tests; they do not replace the main estimate of performance.
Wang et al. 2023 · Shumailov et al. 2024 · Gerstgrasser et al. 2024
Gebru et al. 2021 · Mitchell et al. 2019 · Sambasivan et al. 2021
### datasheet extract — Turkish product reviews
COMPOSITION
235,165 reviews; 233,508 after exact de-duplication (1,657 extra rows,
0.70%). 93.7% positive. 77 texts carry both labels. Product category,
date, and reviewer are not available.
LICENCE AND PROVENANCE
The licence file of the original GitHub repository and the licensing
section of the card say CC BY-SA 4.0; the licence field at the top of
the Hugging Face page says "unknown" (checked on 10 October 2026).
The site and the date of collection are not documented.
LABELS
Provenance unknown; how the labels were derived is not documented
(possibly from star ratings). No guideline document exists. Whether
inter-annotator agreement was measured is not reported.KNOWN LIMITATIONS
- 20.03% of the test reviews contain one of the connectives ama/fakat/
ancak/lakin; that alone does not show mixed sentiment or a problem
with the binary schema. Model macro-F1 on this subset is 72.11,
against 77.72 on the rest.
- The 40 test reviews the model disputed with its highest scores were
examined by one reader: 11 clear label contradictions, 20 schema
problems. These proportions cannot be generalised to the corpus.
- In 100 randomly selected test rows the same reader found 0 clear
contradictions and 7 undecidable rows. The "rule of three" upper
bound of about 3% for zero observations holds under independent
sampling and the same definition of an error.
- Selection bias: reviewers are self-selected. Non-reviewers absent.
(Not measured.)Not recommended without independent, task-specific validation: deployments where errors on the negative class are costly. A good datasheet also records, explicitly, the limitations it cannot put a number on.
| activity | the information it can give | when to do it |
|---|---|---|
| read 100 random rows by hand | candidates for clear contradictions and ambiguity; a wide uncertainty interval for the rate | when the data arrives, before modelling |
| write a guideline with examples | how clear the decision rules are | before bulk annotation |
| measure two humans’ agreement on a shared sample | a disagreement table and a kappa that depends on the sampling | in the guideline pilot |
| out-of-fold flagging + hand reading | candidate rows to examine | once training data exists |
| leakage audit | risks in the split and the preprocessing | before reporting a result |
The quality of the evaluation labels has to be reported along with the model’s score.
Two independent sources of labels agree on 93% of items. Is that enough?
How many macro-F1 points did mislabelling 10% of the source class cost?
Model A beats model B by 1.2 macro-F1 on your test set. Ship A?
An automated audit flags 92 of your 40,000 training labels. Delete them?
You have budget for 5,000 careful labels or 40,000 cheap ones. Which?
Three of the chapter’s seven questions. When you answer, give the direction and which split rather than a single rate.
SKIP allowedDo not compare your kappa to this chapter’s 0.2698: that one is gold-versus-a-lexicon, not human-versus-human. Full text: chapter 5 in the book.
Uygulamalı Doğal Dil İşleme · Applied NLP