Bag-of-Words & Text Vectorization
NLP
Chapter 2 · Bag-of-Words & Text Vectorization
nlp1-1 left off with clean tokens — still just words. This chapter turns them into the one thing every model since ml1-3 has actually required: numbers.
The Bag-of-Words Idea
Build a vocabulary — every unique word across the whole corpus. Represent each document as a vector with one position per vocabulary word, where the value is how many times that word appears in that document. "Bag" because order is discarded entirely — as if every word were tipped out of the document into an unordered bag and only the counts were kept.
Doc 1: "free money now" Doc 2: "call me now" Vocabulary: [call, free, me, money, now] Doc 1 vector: [0, 1, 0, 1, 1] Doc 2 vector: [1, 0, 1, 0, 1]
Feeding This Directly Into ml1-5's Own Logistic Regression
from sklearn.feature_extraction.text import CountVectorizer from sklearn.linear_model import LogisticRegression vectorizer = CountVectorizer() X = vectorizer.fit_transform(documents) # exactly the "X" ml1-3/ml1-5 already used y = labels # spam / not spam model = LogisticRegression() model.fit(X, y) # ml1-5's own workflow, unchanged
ml1-3's own mileage and year columns, or ml1-5's own salary and age. Nothing about LogisticRegression.fit() changes at all — it has no idea the columns started life as words rather than numeric measurements.
Two Real, Practical Details
Sparse Vectors
A real corpus can easily have a vocabulary of tens of thousands of unique words — but any single document only ever uses a tiny fraction of them. The resulting vectors are overwhelmingly zeros, a property called sparsity. This is a genuinely different practical concern from ds1's own typically dense numeric tables, though most libraries (including CountVectorizer) store and compute with sparse vectors efficiently rather than wastefully storing every zero.
Words Never Seen During Training
The vocabulary is built from the training data. A brand-new document at prediction time containing a word the vocabulary has never seen simply has nowhere to put it — that word is typically dropped entirely, silently. A real, honest limitation worth naming plainly.
What This Chapter Deliberately Doesn't Fix
"dog bites man" from "man bites dog" — both produce the identical set of word counts. This isn't an oversight; nlp1-4 demonstrates exactly why this matters, concretely, before nlp1-5 and nlp1-6 separately fix it.
Hands-On Exercises
Using this chapter's own two-document example, build the bag-of-words vector for a third document, "free call now," and explain how you determined each position's value.
📄 View solutionExplain, using this chapter's own finding-box, precisely why LogisticRegression.fit() requires no code changes at all to work with bag-of-words vectors instead of ml1-3's own numeric features.
📄 View solutionExplain what sparsity means for a bag-of-words vector, and explain why a real corpus's own vocabulary size makes sparsity essentially unavoidable rather than a rare edge case.
📄 View solutionChapter 2 Quick Reference
- Bag-of-words — one vector position per vocabulary word, value = count in that document, order discarded entirely
- Feeds directly into ml1-5's own
LogisticRegression.fit()— text becomes ordinary tabular data, one column per word - Sparsity — real vocabularies are huge; any one document's own vector is overwhelmingly zeros
- Words unseen during training simply can't be represented at prediction time — dropped silently
- Word order is completely lost — deliberately left unresolved, demonstrated concretely in nlp1-4
- Next chapter: TF-IDF — Weighting Words by Distinctiveness