Classifying Text
Turn documents into labels. Bag-of-Words as the canonical sparse representation, then three linear classifiers — Naïve Bayes, logistic regression, and the linear SVM — plus how to grade them with precision, recall and F1, and spelling correction as Naïve Bayes in disguise.
01 · Motivation
What text classification is
Text classification assigns a piece of text to one or more predefined categories. It is the workhorse of applied NLP — spam filters, sentiment, authorship attribution, content moderation, query-intent, ticket routing, voice-assistant intent.
The pattern is always the same: a document arrives, we need a label, and we have past (document, label) pairs to learn from. That last assumption — labelled training data — is what makes this supervised learning.
The four shapes of classification
- Binary — two mutually exclusive classes. “Is this spam?” Output is one bit.
- Multiclass — one label from mutually exclusive classes. “Which department?”
- Multilabel — any subset of classes (including none/all). “Tag this article.” Treated as independent binary problems.
- Ordinal — labels have a natural order. “Predict the 1–5 star rating.” Predicting 4 for a true 5 is much less wrong than predicting 1.
Name the shape
(a) language ID of a tweet → multiclass; (b) hashtag suggestion → multilabel; (c) Amazon star rating → ordinal; (d) toxic/non-toxic → binary. Trap: calling multilabel “multiclass with more classes” — multilabel classes are not mutually exclusive.
02 · Refresher
The supervised learning loop
Fix the vocabulary now; it means the same thing in every later chapter. An instance is one example (a document). A feature vector is its numerical representation. A label is the target. A model maps features to a predicted label; its parameters are learned from data.
Hyperparameters are knobs on the learning algorithm (regularisation strength, learning rate, smoothing constant) — not learned from training data. Tune them on a held-out validation set; touch the test set only once, at the end.
Overfitting in one sentence
A model overfits when it memorises noise instead of signal — training error falls while validation error climbs. In text classification this is the default, because you almost always have far more features (vocabulary terms) than documents. That is why every serious text classifier uses regularisation or smoothing.
03 · Representation
Bag-of-Words — the canonical sparse representation
Fix a vocabulary . Represent each document as a vector where is the count (or 0/1, or TF-IDF — Ch. 3) of word .
BoW captures word identity and frequency; it loses word order. “man bites dog” and “dog bites man” map to the same vector.
Heap’s law says vocabulary grows roughly as the square root of corpus length; Zipf’s law
says token frequency is roughly inversely proportional to rank. Together they explain the shape of
BoW vectors: any single document uses a tiny slice of the vocabulary, so its vector is mostly zeros.
Store them sparse — lists of (index, count) pairs — never dense arrays.
Our running example
One six-sentence toy corpus threads through the whole guide — Bag-of-Words here, then TF-IDF, cosine similarity and the inverted index in Chapter 3 — so you watch a single dataset flow through every representation. Three positive (👍) and three negative (👎) one-line reviews:
- 👍 the film was brilliant and moving
- 👍 a brilliant and clever film
- 👍 the acting was great and moving
- 👎 the film was boring and dull
- 👎 a dull and predictable film
- 👎 the acting was boring and weak
The shared words (the, film, and, was, a, acting) carry no class signal; the polar words (brilliant, moving, clever, great vs boring, dull, predictable, weak) do. The AI tutor grounds its worked examples in exactly these sentences.
Build a Bag-of-Words term–document matrix
Each document becomes a vector of word counts (or 0/1). Add a document of all-distinct words and watch the matrix get sparser — the curse of dimensionality lurking under every BoW model.
| doc | a | acting | and | boring | brilliant | clever | dull | film | great | moving | predictable | the | was | weak |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| D1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 |
| D2 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| D3 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 0 |
| D4 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 |
| D5 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 |
| D6 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
When BoW is fine, when it isn't, and synonyms
- Fine for spam and topic classification of long documents — characteristic words carry the signal regardless of order.
- Not fine for sentiment of short compositional sentences (“this film was not bad”) — drop the order and you drop the negation.
- Synonyms get zero similarity because each term is its own orthogonal dimension: “brilliant” and “great” share no axis. Dense embeddings (Ch. 4) exist to fix this.
- Trap. Calling BoW “useless.” It is a strong, fast baseline that beats fancier methods on long-document tasks.
04 · Probabilistic baseline
Naïve Bayes — Bayes’ rule with a bold assumption
We want the most probable class given the document, . Bayes’ rule swaps the conditioning, and is constant across classes so it drops out of the argmax:
The naïve step: assume words are conditionally independent given the class. Obviously false for real text, but it makes the likelihood factorise into one-dimensional probabilities we can count:
If a test word never appeared in some class, its raw annihilates the whole product — the zero-count catastrophe. Fix it with a pseudo-count (Laplace smoothing, the default):
Work in log-space — the product becomes a sum, avoiding underflow. The additive form is exactly a linear classifier in BoW space.
Naïve-Bayes step-through
Each test-doc word adds a log P(w | c) term to each class. The class with the largest log-posterior wins. Set α = 0 and an unseen test word sends one log to −∞.
predicted class → pos|V| = 14 · 6 training docs
Why 'naïve', and why it works anyway
- Naïve = conditional independence of features given the class. Neighbouring words (New/York, machine/learning) are correlated, so the assumption is false.
- Works because we only need the argmax over classes to be right, not the calibrated probability; correlated features double-count on both sides and the bias often cancels.
- Cost. Predicted probabilities are systematically overconfident — prefer logistic regression if you need calibration.
- Trap. With a single unseen word annihilates a class’s score. Always smooth.
05 · Calibrated workhorse
Logistic regression — a discriminative linear classifier
Naïve Bayes models and inverts it (generative); logistic regression models directly (discriminative). Compute a score ; is the decision hyperplane. Squash the score into a probability with the sigmoid:
From score to probability — the sigmoid
A score in (−∞, +∞) isn’t a probability. The logistic function squashes it into (0, 1), taking 0.5 at the boundary. Larger weights make the transition sharper — almost a step.
σ(0.00 × 1.0) = P(y=1) = 0.5000 · prediction: positive
Fit the weights by minimising the negative log-likelihood (binary cross-entropy):
Cross-entropy sends loss to as the predicted probability of the correct class goes to zero, and it is convex in — unlike MSE on top of a sigmoid. Because text has far more features than documents, add a penalty : L2 (ridge) shrinks all weights gently; L1 (lasso) drives many to exactly zero (sparse, interpretable).
Generative vs discriminative — same hyperplane, two routes
Both NB and LR fit a linear boundary in BoW space. NB estimates each independently from counts; LR jointly optimises all weights so correlated features are traded off rather than double-counted. That joint optimisation is why LR usually wins given enough data — and why NB usually wins when data is scarce (less to overfit on).
LR vs NB, and when to prefer NB
LR is discriminative (models , fit by gradient descent on cross-entropy); NB is generative (models , closed-form one pass). Prefer NB when data is very small or you need a fast, low-variance baseline. Trap: LR does assume the log-odds are linear in — it is not assumption-free.
06 · Margin maximiser
Support Vector Machines — geometry, not probability
A third route to a linear boundary, motivated by a different question: not which hyperplane makes the labels most likely? but which hyperplane sits as far from the data as possible? The widest buffer is the margin; the points on its edge are the support vectors — the only training points that affect the boundary. Real text isn’t separable, so allow intrusions at a price — the hinge loss:
A point outside the margin on the correct side pays zero — so SVMs ignore easy cases and focus on the hard ones near the boundary. The full objective adds , equivalent to maximising the margin.
Reference Three classifiers, one comparison
| Property | Naïve Bayes | Logistic Regression | Linear SVM |
|---|---|---|---|
| Type | Generative | Discriminative (probabilistic) | Discriminative (geometric) |
| Optimises | Joint likelihood | Cross-entropy | Hinge loss + margin |
| Training | Closed-form, one pass | Iterative (gradient descent) | Iterative (convex QP / SGD) |
| Output | Label + overconfident prob. | Label + calibrated probability | Label + signed score (not a prob) |
| Best when | Little data, fast baseline | You need calibrated probabilities | High-dim sparse text, want robustness |
| Key knob | Smoothing | L1/L2 strength | Margin trade-off |
Why far-away points are irrelevant to an SVM but not to LR
SVM: hinge loss is exactly zero outside the margin, so distant points contribute no gradient — only support vectors matter. LR: cross-entropy is positive everywhere, so even a correctly classified point at score still pulls a little. SVMs are thus less sensitive to outliers far from the boundary.
07 · Evaluation
Confusion matrix, precision, recall, F1
Accuracy lies. On a 99%-ham dataset, “predict ham” scores 99% accuracy and catches zero spam. For a binary task with positive class “spam”:
TP / TN
FP — false alarm
FN — miss
The metrics
Confusion matrix · precision / recall / F₁
Move the threshold. A higher threshold predicts “positive” less often — precision rises, recall falls. F₁ is their harmonic mean; the sweep shows where it peaks.
| pred 1 | pred 0 | |
|---|---|---|
| actual 1 | TP · 92 | FN · 8 |
| actual 0 | FP · 16 | TN · 84 |
For multiclass, macro-F1 averages per-class F1 equally (honest for rare classes); micro-F1 pools all counts first (dominated by frequent classes; equals accuracy in single-label problems). The ROC curve plots TPR vs FPR across all thresholds; AUC is the threshold-independent probability that a random positive scores above a random negative.
Compute the metrics, then choose what to cite
TP = 80, FP = 20, FN = 5, TN = 895. Accuracy = 975/1000 = 0.975; Precision = 80/100 = 0.80; Recall = 80/85 ≈ 0.94; F1 ≈ 0.86. Accuracy hides that 20% of “spam” flags are false alarms — cite precision and recall together; for a spam filter, push precision up by raising the threshold.
08 · Applied
Spelling correction — Naïve Bayes meets the noisy channel
Treat the misspelling (“acress”) as a corrupted version of an intended word , and pick the most probable . Bayes’ rule, denominator dropped:
The error model needs “how close” two strings are: Levenshtein edit distance, the minimum number of single-character insertions, deletions, or substitutions, computed by dynamic programming:
Initialise , ; fill left-to-right, top-to-bottom; the bottom-right cell is the answer.
Levenshtein edit-distance matrix
Type two strings. Each cell is the minimum of delete (↑+1), insert (←+1), and substitute (↖+0/+1). The highlighted path is one optimal alignment; the corner is the edit distance.
| ε | s | i | t | t | i | n | g | |
|---|---|---|---|---|---|---|---|---|
| ε | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| k | 1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| i | 2 | 2 | 1 | 2 | 3 | 4 | 5 | 6 |
| t | 3 | 3 | 2 | 1 | 2 | 3 | 4 | 5 |
| t | 4 | 4 | 3 | 2 | 1 | 2 | 3 | 4 |
| e | 5 | 5 | 4 | 3 | 2 | 2 | 3 | 4 |
| n | 6 | 6 | 5 | 4 | 3 | 3 | 2 | 3 |
Conditioning on context too — — is exactly a Naïve Bayes classifier: the class is , the features are the misspelling and the surrounding context, assumed conditionally independent given .
Edit distance, and why BoW cosine is the wrong tool
with unit costs. BoW cosine fails for spelling because it indexes by words, not characters: “acress” and “actress” are orthogonal dimensions with zero cosine, even though one is a typo of the other. Spelling needs sequence-aware character distance.
09 · Self-check
Five questions before you move on
A classifier reports TP=40, FP=10, FN=20, TN=130. Which value is the recall?
In Naïve Bayes, "free" appears 0 times in class ham; |V| = 100, class-token total = 500. With α = 1, P("free" | ham) is:
You lower the decision threshold of a logistic classifier from 0.5 to 0.3. What happens to precision and recall?
Which statement best captures L1 vs L2 regularisation in logistic regression?
A linear SVM is trained; you add 1,000 new points all far on the correct side (outside the margin). What happens to the boundary?
10 · Recap
One-screen summary
Chapter 02 — load-bearing ideas
- Text classification is a vector → label problem in four shapes (binary, multiclass, multilabel, ordinal). Pick the shape before the model.
- Bag-of-Words gives sparse, high-dimensional vectors — loses order, keeps word identity. Zipf and Heap explain the shape.
- Naïve Bayes (generative, one pass, smoothed) vs logistic regression (discriminative, calibrated) vs linear SVM (margin, robust) — three routes to similar hyperplanes.
- Smoothing (NB) and regularisation (LR, SVM) exist because text always has more features than documents. L1 → sparse; L2 → gentle shrinkage (safer default).
- Accuracy lies on imbalanced data. Use precision, recall, F1, macro-vs-micro; the threshold trades precision against recall.
- Spelling correction = noisy channel = Naïve Bayes, with Levenshtein edit distance as the error model.
11 · Exam · past papers
Past-paper questions
Q10Which task involves assigning a label from a predefined set of categories to a piece of text?
Q1The main reason for performing stemming before building a text classifier is to:
Q5A Naïve Bayes spam classifier has 2,000 spam and 8,000 not-spam emails. What is the prior P(spam)?
Q9With P("win"|spam)=4/10, P("win"|not-spam)=1/10, P(spam)=2/10, what is P(spam | "win")?
Q12"The size of the vocabulary grows roughly in proportion to the square root of the length of the collection" is a statement of:
Q13Zipf's law states that:
Q-LR-NBWhich is TRUE of logistic regression compared with Naïve Bayes?
Q-SVMIn a soft-margin linear SVM, which training points determine the decision boundary?
Q-ACCWhy is accuracy a poor metric on a 99%-ham email dataset?
Q-EDThe Levenshtein distance between "kitten" and "sitting" is: