What this is

About 25 of your own labels beat 5,574 borrowed ones

Barely, and the first way you measure it is wrong. A filter trained on 5,574 labelled SMS messages (UCI SMS Spam Collection) and applied to 1,956 YouTube comments (UCI YouTube Spam Collection, both CC BY 4.0) scores 53.2% accuracy at the default 0.5 cutoff — barely above the majority class, which reads as total failure. It is not. The two corpora have very different spam rates, 13.4% against 51.4%, and a classifier's default cutoff encodes the rate it was trained on. Moving the cutoff to the target's own rate — which needs an estimate of how much spam you have, not labels saying which comments are spam — lifts accuracy to 69.4% with the model and its predictions completely unchanged. What genuinely transferred is modest: AUC 0.774 borrowed against 0.982 for a filter trained on the target's own comments and evaluated leave-one-video-out. Training on a growing sample of in-domain comments passes the borrowed corpus at about 25 labels — roughly one two-hundredth of the borrowed set, and an afternoon's work.

This is a real analysis on a real dataset, not an illustration. The code is published, it runs in under two minutes, and a verification script re-runs it from scratch and fails if any headline number moves.

Every figure below is read from results.json, which is written by the analysis itself. Where the result is unflattering it is published unchanged — the findings and the limitations both come straight out of the run.

Source figures are in the currency of the data: sterling for the UK retail and wholesale sets, euro for the Portuguese bank set. Dollar amounts are converted at 1.55 USD/GBP and 1.40 USD/EUR, roughly the averages for the periods the data covers — stated assumptions, not live rates.

How this is checked

verify.py --only 27 deletes this project's results, re-runs it and diffs every published number before the page ships.

The pipeline
Findings

What the analysis found, including the results that went against us

Each of these came out of the run. None has been softened.

THE OBVIOUS MEASUREMENT SAYS THE TRANSFER FAILS COMPLETELY, AND IT IS WRONG. A filter trained on 5,574 labelled SMS messages, applied to 1,956 YouTube comments at the default 0.5 cutoff, scores 53.2% accuracy against a majority-class rate of 51.4%, catching 9.5% of the spam. That reads as total failure and it is the number you get by running the obvious code. It is measuring the wrong thing.

Your own labels against five thousand borrowed ones

Accuracy against the number of in-domain labels used for training, with the best result from all 5,572 borrowed labels shown as a flat line. The curve crosses it early.

run.py section 6: held out on one video, averaged over five choices and ten draws.

THE DEFAULT CUTOFF ENCODES THE SPAM RATE OF THE CORPUS THE MODEL LEFT BEHIND. SMS is 13.4% spam and these comments are 51.4% — a factor of 3.8. A model trained where spam is rare puts most of its probability mass below 0.5, so almost nothing clears the bar in a population where spam is common. Move the cutoff to the target's own rate — which needs an estimate of how much spam you have, not labels saying which comments are spam — and accuracy goes from 53.2% to 69.4%, and recall from 9.5% to 70.5%. The model never changed and neither did its predictions.

Accuracy by threshold, transferred filter

Accuracy of the borrowed filter on YouTube comments as the decision threshold moves. The default of 0.5 sits far from the best available cutoff, because it encodes the spam rate of the corpus the model was trained on.

run.py section 4: one model, one set of predictions, threshold swept.

WHAT ACTUALLY TRANSFERRED IS MODEST, AND AUC IS HOW YOU SEE IT. The borrowed filter's AUC on these comments is 0.774. AUC reads the ranking alone and is unaffected by the threshold, which is exactly why it is the honest measure when a model moves between populations — accuracy at a fixed cutoff conflates how well the model separates the classes with a decision rule calibrated somewhere else.

Detection quality per video

Area under the ROC curve for each held-out video when the filter is trained on the other four. Five videos is a thin basis for a general claim.

run.py section 5: leave-one-video-out.

A FILTER TRAINED ON THE TARGET'S OWN COMMENTS SCORES 0.982 AGAINST 0.774 BORROWED. Trained on four videos and tested on the fifth, held out entirely, the in-domain filter reaches 93.3% accuracy. The gap to the borrowed filter is the cost of using someone else's corpus, and it is large.

ABOUT 25 OF YOUR OWN LABELS BEAT ALL 5,574 BORROWED ONES. Training on a random sample of in-domain comments and testing on a held-out video, accuracy passes the best the borrowed corpus achieves at roughly 25 labels — about one 223th of the borrowed set. For a team deciding whether to label their own data, that is the number that matters, and an afternoon covers it.

SHUFFLING THE SPLIT WOULD HAVE ADDED 2.0 POINTS FOR NOTHING. Pooled five-fold cross-validation over all the comments scores 95.3% against 93.3% leave-one-video-out. Comments under one video share vocabulary, campaigns and posting bots, so a shuffled split trains on the same video it tests on and measures memorisation as much as detection. The gap is small here and rests on five videos, but its direction is the one that flatters.

THE RANKING IS STABLE ACROSS VIDEOS AND THE DECISION IS NOT. Held-out AUC varies only from 0.983 to 0.990 across the five videos, while accuracy at the same fixed cutoff spans 89.4% to 95.9% — a range of 6.5 points. It is the threshold lesson again at a smaller scale: what a model knows travels between populations more reliably than where you should cut it, and a single accuracy figure conflates the two.

The detail

Full results tables

The same model, two thresholds

The same model, two thresholds
MeasureDefault 0.5 cutoffCutoff moved to the local spam rate
Accuracy53.2%69.4%
Recall on spam9.5%70.5%
AUC (unchanged — the ranking is the same)0.7740.774

Per-video, trained on the other four

Per-video, trained on the other four
VideoCommentsAUCAccuracy
Eminem4480.98393.1%
KatyPerry3500.98394.9%
LMFAO4380.99095.9%
Psy3500.98689.4%
Shakira3700.98792.7%

How many of your own labels you need

How many of your own labels you need
In-domain labelsAccuracy
1060.5%
2575.3%
5081.0%
10086.3%
20089.7%
40091.5%
80092.4%
150093.2%

Limitations

Stated by the analysis, not added afterwards. A project without these is not finished.

  • Five videos is a thin basis for a general claim. Every per-video figure rests on 350 to 448 comments, and the pooled-versus-held-out gap in particular rests on five clusters. The direction of these results is clear; their magnitude on any other corpus is not established by this one.
  • The comments were collected in 2013 and 2014 and spam is adversarial — it moves precisely because filters catch it. Nothing here supports a claim about how any filter would perform on comments written now. What transfers is the measurement lesson, not the accuracy.
  • Author names were dropped at load and every run of digits in the comment text was replaced before anything read it — 56 comments contained one. These are real messages written by real people, some containing contact details, and none of it is needed to classify a comment. Digits are replaced rather than deleted because 'call this number' and 'call' are different sentences, but no number survives into the model, the charts or this page.
  • Both corpora label English text at message length, so nothing here transfers to long-form content, other languages, or media. Two datasets that are both 'spam or not' turn out to be very different problems, which is the finding — and it applies to this pair, not to corpus transfer in general.
  • The threshold correction uses the target's overall spam rate, which a team would have to estimate. A wrong estimate moves the cutoff and the accuracy with it, so the improvement reported here is the best case for that method rather than what an operator would reliably obtain.
  • TF-IDF with logistic regression is deliberately ordinary. A modern text model would score higher on both sides of the comparison, and might narrow or widen the gap — this project does not test that, and its subject is the corpora rather than the architecture.

Data: UCI YouTube Spam Collection with UCI SMS Spam Collection, UCI YouTube Spam Collection with UCI SMS Spam Collection, CC BY 4.0. 7,528 rows, YouTube comments 2013-2014; SMS collected 2011-2012.

Libraries and methods this analysis used

Read from this project's own run.py when the page was built — 410 lines of it. Not a list of everything we know; a list of what this analysis imports and calls.

7 names from NumPy appear in this analysis.

  • array_split
  • concatenate
  • errstate
  • isfinite
  • linspace
  • quantile
  • random
Verification

How every number on this page is checked

A script deletes each result file, re-runs the project and diffs the output. If a headline figure moves, the check fails, and the page does not ship. That is the only reason to believe anything on this page.

Running this method on your own data

The method above transfers; the result will not. Send us a extract and we will tell you what is forecastable in it and what is not, before anyone signs anything.