16 · Spam classifier: end-to-end with BOW
Build a production-shaped spam classifier with CountVectorizer + LogisticRegression — the canonical NLP project that ties every classical lesson together.
Build an end-to-end spam classifier with BOW + LogisticRegression — the canonical NLP project that ties every classical lesson together.
Without this:
All the chapter pieces stay disconnected; the project shows the assembly.
Every concept you have learned so far — tokenization, stopwords, Bag of Words, n-grams, TF-IDF — exists to serve one purpose: feed a classifier. This lesson assembles those pieces into a complete, production-shaped pipeline.
The task is spam detection: given an SMS message, predict whether it is spam or ham (legitimate). This is a binary classification problem with heavy class imbalance (spam is typically 10–20 % of traffic), adversarial inputs (spammers actively try to evade classifiers), and high asymmetric error cost (a false positive — flagging a real message as spam — is annoying but a false negative — letting phishing through — is dangerous).
The pipeline has three stages:
- Vectorize — CountVectorizer with bigrams converts each message into a sparse count matrix. Bigrams capture phrases like "free prize" that unigrams miss individually.
- Classify — LogisticRegression on the count matrix. A linear model over BOW features is the standard pre-deep-learning spam classifier.
- Evaluate —
classification_reportgives precision, recall, and F1 per class. Never rely on accuracy alone with imbalanced classes.
After this lesson you will also inspect the model's feature importances — which n-grams most strongly signal spam and ham — and run predictions with confidence scores on unseen messages.
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Production checklist: class_weight, honeypot rules, humans in the loop, threshold tuning
What is the most dangerous type of error in a spam classifier?
- The canonical spam-detection pipeline is: CountVectorizer(ngram_range=(1,2), stop_words='english') → LogisticRegression. Bigrams capture multi-word spam signals like 'free prize' and 'click now' that unigrams miss when words appear separately.
- Never evaluate with accuracy alone on imbalanced classes — always inspect classification_report per class. A model predicting 'ham' for everything gets high accuracy but zero spam recall.
- Feature importance via LogReg coefficients reveals what the model learned: top positive coefficients are spammy tokens (FREE, WINNER, URGENT), top negative coefficients are hammy tokens (schedule, meeting, home). Inspecting these catches bugs and builds trust.
- Production spam classifiers add: class_weight='balanced' for imbalanced data, rule-based honeypot pre-filters, human review of uncertain cases, and threshold tuning via precision-recall curves rather than the default 0.5 cutoff.
Gmail, Outlook, SMS spam filters, and phishing-URL classifiers all use this exact pipeline shape. The feature space grows to millions of n-grams in production, but the CountVectorizer + LogisticRegression skeleton is identical. The same pattern applies to content moderation (hate speech, abuse detection), intent classification, and any binary text-labeling task where interpretability matters.
If you remove it: Pieces stay disconnected; this project is the synthesis. Without building a full end-to-end pipeline yourself, CountVectorizer, LogisticRegression, classification_report, and feature inspection all feel like separate tools rather than a coherent production workflow.