Chapter 3: Text Representation
Transform raw text into numerical vectors that machine learning models can process. Master classical techniques from simple count-based methods to dimensionality reduction, building the foundation for modern embeddings.
- Topics
- 6
- Demos
- 3
- Videos
- 3
- Min read
- 47
Chapter Overview
Before any NLP model can process text, words and documents must be converted into numerical representations. This chapter covers the classical methods that dominated NLP for decades and still serve as strong baselines today.
The central challenge is capturing meaning in numbers. A naive approach (assigning word 1 = 1, word 2 = 2) imposes a false ordering. Instead, we need representations where similar texts map to nearby vectors. The methods here range from simple count-based approaches (Bag of Words) to statistically weighted schemes (TF-IDF) to techniques that capture word relationships through co-occurrence patterns.
Understanding these foundations is essential because:
- Bag of Words and TF-IDF remain competitive for many classification tasks
- Co-occurrence matrices inspired the word embeddings revolution (Word2Vec, GloVe)
- Dimensionality reduction techniques (SVD, PCA) are used everywhere in modern NLP pipelines
- Every modern embedding method can be understood as improving upon these classical approaches
This chapter covers:
- Bag of Words: Converting documents to count vectors
- TF-IDF: Weighting terms by importance across a corpus
- N-grams: Capturing local word order and phrases
- One-Hot Encoding: Binary word representations and their limitations
- Co-occurrence Matrices: Learning from word context patterns
- Dimensionality Reduction: Compressing sparse representations into dense vectors
Chapter Roadmap
Click any topic to jump in
Bag of Words
Count-based document vectors — ignoring word order to capture which words appear and how often.
Weighting by importance and capturing local order
TF-IDF
Weighting terms by local frequency and global rarity — the workhorse of information retrieval.
N-grams
Capturing local word order as token tuples — bigrams, trigrams, and language model probabilities.
Simple indicators and context-based statistics
One-Hot Encoding
Binary indicator vectors — the simplest representation and why it fails at scale.
Co-occurrence Matrices
Counting word-context pairs and PMI weighting — the statistical foundation of word embeddings.
Dimensionality Reduction
PCA, SVD, and LSA — compressing sparse representations into dense vectors that generalize.
Topics
6 topics in this chapter
A spam filter receives the email "WIN a FREE prize now". A sentiment classifier receives "the battery died after two days". Both are machine-learning models, and machine-learning models take fixed-length vectors of numbers, not strings of varying length. How do we turn arbitrary text into such a vector while keeping enough signal to separate spam from real mail, or praise from complaint?
The previous chapter, Text Preprocessing, produced clean tokens through tokenization, stemming, stopword removal, and normalization. This chapter, Text Representation, turns those tokens into numbers, and Bag of Words is the simplest answer: count each vocabulary word in the document and ignore order entirely. The topic starts with vocabulary construction, which fixes the dimensions of every vector. Count vectors and the document-term matrix follow, then term frequency, which normalizes counts by document length. It ends with the limitations of the model, namely lost word order, huge sparse vectors, and no notion of meaning, which motivate the rest of the chapter: TF-IDF, n-grams, co-occurrence statistics, and dense vectors.
Definition
A Bag of Words representation maps a document to a vector over a fixed vocabulary , where is the number of times word occurs in . Word order, grammar, and position are discarded; only the multiset of tokens remains, so the vector is sparse and has one dimension per vocabulary word.
In this topic
- 1Vocabulary Construction
- 2Count Vector Representation
- 3Term Frequency (TF)
- 4Limitations of Bag of Words
Vocabulary Construction
Before any document becomes a vector, the model needs a fixed list of dimensions. The vocabulary is the union of unique tokens across the training corpus , and each word receives a permanent index, so sets the length of every document vector. Vocabularies keep growing with corpus size, roughly as a power of the token count by Heaps' law, so practical pipelines prune them: drop words found in fewer than a minimum number of documents, drop stopwords or words found in almost every document, or keep the top by frequency. Words seen only at test time have no index and are silently ignored.
The vocabulary grows sublinearly with corpus size by Heaps' law: . Each document vector has at most non-zero entries out of dimensions. For a typical corpus with and average document length 200 words, each vector is zeros — sparse matrix storage is essential.
Build the vocabulary for the corpus: ["the cat sat", "the dog ran", "a cat ran"]. What is the dimensionality?
Count Vector Representation
Given the vocabulary, each document becomes a vector whose -th entry counts how often word appears in . Stacking these vectors row by row gives the document-term matrix , with one row per document and one column per word. Because a document uses a few hundred distinct words out of tens of thousands, more than 99 percent of entries are zero, so libraries store in sparse formats such as CSR that keep only the non-zero values and their positions. Similarity between documents is then a dot product or cosine between rows. Raw counts favor long documents, which is why the next step normalizes them.
The document-term matrix has . Two documents sharing words have dot product . Cosine similarity normalizes this by vector magnitudes, removing the length bias: longer documents do not automatically appear more similar to everything.
Using vocabulary [a, cat, dog, ran, sat, the], represent "the cat sat" and "a cat ran" as count vectors.
Term Frequency (TF)
Raw counts grow with document length: a review pasted twice has every count doubled, though its content is unchanged. Term frequency divides each count by the total number of tokens in , turning the count vector into a probability distribution over the vocabulary that sums to 1. Variants make different trade-offs. Binary TF records presence only, which works well for short texts. Logarithmic TF, , damps words repeated many times. Augmented TF divides by the largest count in the document. TF alone still rewards frequent function words such as "the", the problem that the next topic, TF-IDF, solves by weighting terms by their rarity across documents.
Term frequency normalizes raw counts to a probability distribution over the vocabulary. The sum for every document, regardless of length. This means TF treats a 10-word tweet and a 10,000-word article on equal footing — the representation captures word proportions, not absolute counts.
Compute TF for every word in "the cat sat on the mat" (6 words total).
Limitations of Bag of Words
Bag of Words makes three simplifying choices, and each one breaks something. It discards order, so "dog bites man" and "man bites dog" get identical vectors; every permutation of a sentence maps to the same point. It uses one dimension per word, so vectors have 50,000 to 100,000 dimensions that are almost all zeros, and models need many examples per feature. It treats every word as an unrelated axis, so "happy" and "joyful" share nothing, and a classifier that learns one never generalizes to the other. The later topics in this chapter each address one gap: TF-IDF weights importance, n-grams restore local order, and co-occurrence statistics begin to capture meaning.
BoW is invariant to word permutation: any reordering of words produces the same vector. Formally, for any permutation , . This means distinct sentences map to the same representation. For a 10-word sentence, that is distinct orderings collapsed into one vector — a massive information loss that n-grams partially recover.
Show that BoW cannot distinguish "the cat chased the dog" from "the dog chased the cat".
Theory Exercise
Problem:
A corpus has 10,000 documents with an average of 200 words each. The vocabulary after preprocessing has 25,000 unique words. (a) What is the shape of the document-term matrix? (b) Estimate the sparsity (percentage of zero entries). (c) Why is sparsity a problem for machine learning?
Hints:
- Each document is a row, each word is a column
Coding Exercise
Problem:
Use scikit-learn's CountVectorizer to convert a list of 3 sentences into a document-term matrix. Print the vocabulary, the matrix shape, and the dense matrix.
Hints:
- Import CountVectorizer from sklearn.feature_extraction.text
Related Problems on PixelBank
Bag of Words counts give "the" one of the largest values in almost every English document, yet the word reveals nothing about what the document is about. A search for "quantum entanglement" should rank a physics paper above a news story that happens to say "the" fifty times. How can we keep the counts but let rare, topical words outweigh common ones?
The previous topic, Bag of Words, built count vectors and normalized them by document length, but every word still counted equally. TF-IDF multiplies each term frequency by an inverse document frequency that shrinks for words found in many documents and grows for words found in few. The topic begins with the TF-IDF formula and a worked score, then studies the IDF factor and why it uses a logarithm. Variants follow, including sublinear TF, smoothed IDF, and L2 normalization, the defaults in scikit-learn. It ends with document retrieval, where queries and documents share one TF-IDF space and are ranked by cosine similarity, the vector space model that powered search engines for decades.
Definition
TF-IDF weights a term in document by , where is the number of documents and is the number that contain . Terms frequent in a document but rare across the corpus receive the highest weights, and a term present in every document receives weight zero.
In this topic
- 1TF-IDF Formula
- 2Inverse Document Frequency (IDF)
- 3TF-IDF Variants
- 4TF-IDF for Document Retrieval
TF-IDF Formula
The TF-IDF score is the product of two terms: TF measures local importance (how frequent is in document ?), and IDF measures global rarity (how many documents contain ?). The logarithm dampens the IDF factor so that a term appearing in 1 out of 1000 documents does not receive a score 1000x higher than one appearing in all documents. Common IDF variants include smooth IDF: to avoid division by zero.
TF-IDF weights a term by . The log-IDF factor downweights common terms: a word appearing in all documents gets weight, while a rare term in 1 document gets . For , the IDF range is . A term in 10 documents has IDF , making it as discriminative as a unique term.
Compute TF-IDF for "cat" in D1 = "the cat sat on the mat", given a corpus of 100 documents where "cat" appears in 5.
Inverse Document Frequency (IDF)
The document frequency counts how many documents contain term at least once. IDF is the log of the inverse of this proportion. Terms appearing in every document get IDF = 0 (no discriminative power). Terms appearing in only one document get the maximum IDF = . The logarithm ensures the scale is manageable -- without it, a term in 1 of 1,000,000 documents would get a weight of 1,000,000.
IDF is the log-inverse of the document frequency proportion: . Each factor-of-10 decrease in df adds to IDF. This logarithmic compression prevents rare terms from dominating: without the log, a term in 1 of 10,000 documents would get weight 10,000 — an unstable extreme. The log maps this to , a manageable scale.
A corpus has 10,000 documents. Compute IDF for terms with df = 10000, 1000, 100, 10, and 1.
TF-IDF Variants
Several variants exist for both TF and IDF components. Sublinear TF: Uses instead of raw TF, dampening the effect of very high frequencies. Smooth IDF: Adds 1 to numerator and denominator to prevent division by zero for unseen terms. L2 normalization: After computing TF-IDF, each document vector is normalized to unit length, making cosine similarity equivalent to a dot product. Scikit-learn's TfidfVectorizer uses smooth IDF and L2 normalization by default.
Sublinear TF replaces raw frequency with . A term appearing 100 times gets score instead of 100 — a compression. This prevents a single repeated word from dominating the vector. The smoothed IDF variant ensures no term gets IDF exactly 0, which would zero out its contribution entirely.
A term appears 100 times in a document. Compare raw TF vs sublinear TF scaling.
TF-IDF for Document Retrieval
In information retrieval, queries are also converted to TF-IDF vectors. Documents are ranked by cosine similarity between the query vector and each document vector. This is the foundation of vector space models used in search engines. The process: (1) Build IDF from the document corpus, (2) Convert the query to a TF-IDF vector using the same vocabulary, (3) Compute cosine similarity with all document vectors, (4) Return top- most similar documents.
Document retrieval scores query against document as . With L2 normalization, , so . Inverted indices make retrieval efficient: for each query term, look up the documents containing it in , then score only those documents. This avoids scanning all documents per query.
A search query is "neural network training". How would TF-IDF rank two documents: D1 about "training dogs" and D2 about "training neural networks"?
Theory Exercise
Problem:
Explain why TF-IDF assigns a score of 0 to stop words like "the" and "is" in most corpora, and describe a scenario where TF-IDF might fail to capture the importance of a word.
Hints:
- Think about the IDF component when df equals N
Coding Exercise
Problem:
Use scikit-learn's TfidfVectorizer to compute TF-IDF vectors for 4 documents. Find the two most similar documents using cosine similarity.
Hints:
- Import TfidfVectorizer from sklearn.feature_extraction.text
Related Problems on PixelBank
A sentiment model built on Bag of Words sees "not good, bad" and "not bad, good" as exactly the same set of words, and it cannot tell the city "New York" from a sentence that mentions "new" and "York" far apart. Counting single words throws away the local order that carries negation, phrases, and names. How much order can we recover while keeping simple counts?
The previous topic, TF-IDF, weighted words by importance but still treated each one in isolation. N-grams count short runs of consecutive tokens instead: bigrams for pairs, trigrams for triples. The topic first defines n-grams and counts how many a sentence produces. N-gram language models follow, predicting the next word from the previous few words with counts and the Markov assumption. Skip-grams then relax adjacency to capture pairs separated by a gap, an idea that returns in Word2Vec. The topic closes with data sparsity, why most n-grams are never observed, and smoothing methods such as Laplace and Kneser-Ney that give unseen sequences a non-zero probability.
Definition
An n-gram is a contiguous sequence of tokens taken from a text, such as a word pair or triple, and a sequence of tokens contains of them. N-gram features add local word order to count representations, and n-gram language models estimate from corpus counts.
In this topic
- 1N-gram Definition
- 2N-gram Language Models
- 3Skip-grams
- 4Data Sparsity and Smoothing
N-gram Definition
Single-word counts lose phrases such as "not good" and "New York". An n-gram slides a window of tokens across the text and records each window: unigrams for , bigrams for , trigrams for . A sequence of tokens yields n-grams, with repeats counted separately. In feature extraction, n-grams are usually added alongside unigrams, as with ngram_range=(1, 2) in scikit-learn, so the model keeps word evidence and gains phrase evidence. The cost is size: the number of possible n-grams grows as , so higher orders produce enormous, sparse feature spaces that need minimum-frequency cutoffs.
An -gram is a contiguous sequence of tokens. A sentence of words contains distinct -grams. For bigrams () of a 10-word sentence: bigrams. The vocabulary of possible -grams is , which grows exponentially: with , there are possible bigrams and possible trigrams — most never observed in any corpus.
Extract all unigrams, bigrams, and trigrams from "the cat sat on the mat".
N-gram Language Models
A language model assigns probabilities to word sequences, which spelling correction, speech recognition, and text generation all need. The chain rule writes as a product of next-word probabilities, but full histories are almost never repeated in a corpus. The Markov assumption truncates the history to the previous words, as in the formula, and the maximum-likelihood estimate divides counts: for a bigram, the count of the pair over the count of the previous word. Model quality is measured by perplexity, the inverse probability of held-out text normalized by its length. Any unseen n-gram gets probability zero, so real models need smoothing.
An -gram language model estimates using the Markov assumption with order . The maximum-likelihood estimate is . Perplexity measures model quality: . Lower perplexity means better predictions.
Given bigram counts: count("I am") = 500, count("I") = 2000, count("am happy") = 50, count("am") = 600. What is P("am" | "I") and P("happy" | "am")?
Skip-grams
Contiguous n-grams miss relations interrupted by other words: in "I really love NLP", the pair (I, love) is split by an adverb. Skip-grams allow up to words to be skipped between elements, so a -skip-bigram pairs each word with any of the next words, and gives ordinary bigrams. They extract more relations from the same text, which helps on small corpora and on text with inserted words, but they also create more features and more noise. The same idea of pairing a word with neighbors inside a window drives the Word2Vec Skip-gram model in the next chapter.
A -skip-bigram pairs with whenever . In a sentence of tokens with , that gives pairs: for , 9 pairs at , 17 at , and 24 at . With no limit on the skip, every pair counts, . The count grows roughly linearly in , so skip-grams multiply the number of features or training pairs by about , capturing relations across inserted words such as adverbs at the price of more noise.
Generate all skip-bigrams with skip distance K=2 from "I really love NLP".
Data Sparsity and Smoothing
Higher-order n-grams are more specific, which makes them rarer. With a 50,000-word vocabulary there are possible bigrams and trigrams, far more than any corpus contains, so most valid sequences have count zero and any sentence containing one gets maximum-likelihood probability zero. Smoothing moves probability mass from seen to unseen events. Laplace adds 1 to every count and to the denominator, as in the formula, but takes too much mass from frequent n-grams. Backoff and interpolation fall back to shorter histories, and Kneser-Ney, the strongest classical method, discounts seen counts and favors words that follow many different histories.
A corpus of tokens contains at most distinct n-grams of each order, while the space of possible n-grams has members, so the observed fraction collapses as grows. Interpolated Kneser-Ney estimates : it subtracts a fixed discount , often about 0.75, from every seen count and gives the freed mass to a continuation distribution. is proportional to the number of distinct words that precede , so "Francisco", frequent but almost always after "San", gets a low continuation probability, while "glasses", which follows many words, gets a high one.
With vocabulary size 1000 and count("the cat") = 0, count("the") = 500, compute P("cat" | "the") with and without Laplace smoothing.
Theory Exercise
Problem:
A corpus has a vocabulary of 10,000 words. (a) How many possible bigrams exist? (b) How many possible trigrams? (c) If your corpus has 1 million words, estimate what fraction of possible trigrams are observed. (d) Why does this make trigram models unreliable without smoothing?
Hints:
- Possible n-grams = |V|^n
Coding Exercise
Problem:
Use scikit-learn's CountVectorizer with ngram_range=(1, 3) to extract unigrams, bigrams, and trigrams from a corpus. Print how many features are generated and show the top 10 most frequent trigrams.
Hints:
- Set ngram_range=(1, 3) in CountVectorizer
Related Problems on PixelBank
A neural network multiplies its input by weight matrices, so every word must become a vector before the first layer can run. The simplest choice gives each vocabulary word its own dimension. But what does that choice imply about similarity between words, and what does it cost when the vocabulary has 50,000 entries?
The previous topic, N-grams, built count features over short word sequences; one-hot encoding represents individual words. Each word becomes a vector of zeros with a single 1 at its index, the building block that Bag of Words sums over a document. The topic starts with the definition and its key property: all distinct one-hot vectors are orthogonal, so "cat" is exactly as far from "dog" as from "quantum". The dimensionality problem follows, comparing the memory of materialized one-hot vectors with dense embeddings. It closes with the embedding layer, showing that multiplying a one-hot vector by a weight matrix just selects one row, which is why every neural NLP model implements its first layer as a lookup table.
Definition
One-hot encoding represents word from vocabulary as the standard basis vector , with a 1 at position and zeros elsewhere. Distinct words are orthogonal and equidistant, so the encoding identifies each word exactly but expresses no similarity between any two words.
In this topic
- 1One-Hot Vector Definition
- 2Dimensionality Problem
- 3Embedding Layer as One-Hot Lookup
One-Hot Vector Definition
Assign every vocabulary word a unique index , and represent it by , a length- vector that is zero everywhere except at position . These vectors form the standard basis of , so a Bag of Words vector is simply the sum of the one-hot vectors of a document's tokens. The encoding is lossless for identity, since each word maps to a distinct vector, but it carries no other information. Any two distinct one-hot vectors have dot product 0 and Euclidean distance . A model therefore cannot transfer anything it learns about "cat" to "dog" through the input representation alone.
A one-hot vector has exactly one non-zero entry at position . The inner product (Kronecker delta): 1 if same word, 0 otherwise. This means every pair of distinct words is equidistant: for all . No notion of similarity exists — 'happy' is as far from 'joyful' as from 'submarine'.
Create one-hot vectors for the vocabulary [cat, dog, fish, bird] and compute the cosine similarity between "cat" and "dog".
Dimensionality Problem
One-hot vectors have one dimension per vocabulary word, so a 50,000-word vocabulary gives 50,000-dimensional vectors with a single non-zero entry each. Materializing all of them as a dense matrix needs entries, as the formula shows, which is 10 GB in float32 for 50,000 words. Even one 512-token sequence of dense one-hot rows takes about 100 MB. No real system stores them this way: sparse formats keep only the index, and neural models pass integer ids directly to an embedding layer. The deeper cost is statistical, since a first layer on one-hot input has weights, and rare words receive too few updates to learn them well.
One-hot encoding maps a vocabulary of words to -dimensional space. A sentence of words becomes a matrix with non-zero entries out of total — zeros for . The memory cost is in dense form but with sparse representation. Embedding layers implicitly convert one-hot to dense: , a simple row lookup.
A vocabulary has 50,000 words. (a) What is the dimensionality of each one-hot vector? (b) How much memory to store all vectors as float32? (c) Compare with 300-dimensional dense embeddings.
Embedding Layer as One-Hot Lookup
An embedding layer is a weight matrix with one row per vocabulary word. Feeding it a one-hot vector computes , and because only position is non-zero, the product just copies row . Libraries therefore implement the layer as an index lookup, as in PyTorch's nn.Embedding, which costs instead of multiplications. During training, gradients reach only the rows of words that appeared in the batch, so each row learns from its own contexts. This links one-hot encoding to the embedding methods of the next chapter: the input stays an index, but the representation becomes dense and learned.
An embedding layer transforms one-hot vectors to dense vectors: . This is mathematically a matrix multiplication but implemented as an index lookup — instead of . The embedding dimension is typically 50--300 for word embeddings and 768--4096 for transformer models, compressing dimensions down by .
Given embedding matrix E with rows: cat=[0.2, 0.8, -0.1], dog=[0.3, 0.7, 0.0], compute the embedding for "cat" using one-hot multiplication.
Theory Exercise
Problem:
Explain why one-hot encoding fails to capture word similarity. Then describe how an embedding layer resolves this, using "king", "queen", "man", "woman" as examples.
Hints:
- Think about distances between one-hot vectors
Coding Exercise
Problem:
Implement one-hot encoding from scratch using NumPy. Create one-hot vectors for a vocabulary, then show that multiplying by an embedding matrix is equivalent to a simple row lookup.
Hints:
- Use np.eye or np.zeros to create one-hot vectors
Related Problems on PixelBank
Bag of Words, TF-IDF, and one-hot vectors all treat "coffee" and "tea" as unrelated dimensions. Yet a reader who has never seen the word "tea" can guess its meaning after seeing it next to "drink", "cup", "hot", and "morning". Can a program learn word meaning the same way, from the company words keep, without any labeled data?
The previous topic, One-Hot Encoding, showed that index-based vectors contain no similarity at all. Co-occurrence matrices turn the distributional hypothesis into numbers: count how often each word appears near each other word, and use those counts as the word's vector. The topic first builds the word-context matrix and shows how window size changes what it captures. Pointwise mutual information then corrects for frequency, asking whether two words co-occur more often than chance predicts, and positive PMI drops its unreliable negative values. The topic ends with truncated SVD, which compresses the sparse matrix into dense vectors, a direct ancestor of GloVe and closely related to what Word2Vec learns in the next chapter.
Definition
A word-context co-occurrence matrix stores in how often word appears within a fixed window of context word . Its rows are distributional word vectors; reweighting them with PMI and reducing them with SVD yields dense vectors in which words used in similar contexts lie close together.
In this topic
- 1Word-Context Co-occurrence Matrix
- 2Pointwise Mutual Information (PMI)
- 3PPMI (Positive PMI)
- 4SVD on Co-occurrence Matrices
Word-Context Co-occurrence Matrix
Given a corpus and a context window of size , the co-occurrence matrix records how many times word appears within positions of word . The matrix is symmetric () when using a symmetric window. Each row of is a word's distributional representation -- words with similar rows have similar meanings. Window size matters: small windows (2-5) capture syntactic relationships; large windows (5-10+) capture topical/semantic relationships.
A co-occurrence matrix has counting how often word appears within a window of word . The matrix is symmetric: . With window size , scanning a corpus of tokens takes time. The resulting matrix has entries but is sparse: most word pairs never co-occur within a window.
Build a co-occurrence matrix with window size 1 for: "I like deep learning. I like NLP."
Pointwise Mutual Information (PMI)
Raw co-occurrence counts are dominated by frequent words: "the" appears near everything, so it looks related to everything. Pointwise mutual information compares the observed joint probability with the product expected if the two words were independent. The log of that ratio is positive for words that attract each other, zero for independent words, and negative for words that avoid each other; in base 2 it is measured in bits. All three probabilities are estimated from the co-occurrence counts. PMI's weakness is rare events: a single co-occurrence of two rare words gets a huge score, so practical systems add count thresholds or smoothing.
PMI measures how much more often two words co-occur than expected: . If and are independent, PMI . If they co-occur more than expected, PMI . The issue: rare co-occurrences produce unreliably high PMI — a pair seen once with expected count gets PMI , a misleading extreme.
Given: P("data") = 0.01, P("science") = 0.005, P("data", "science") = 0.002. Compute PMI.
PPMI (Positive PMI)
Positive PMI clamps negative values to zero. This is important because: (1) Negative PMI values are unreliable -- the absence of a co-occurrence could mean the words are unrelated OR that we simply have not seen enough data. (2) Sparse PPMI matrices are more memory-efficient (many zeros can be stored in sparse format). (3) Empirically, PPMI matrices produce better word representations than raw PMI. PPMI word vectors have been shown to be competitive with Word2Vec on many benchmarks.
PPMI clips negative values: . This removes anti-correlations (words that co-occur less than expected) which are noisy and uninformative. The resulting matrix is non-negative and sparse — most entries are zero because most word pairs are independent. PPMI word vectors outperform raw count vectors on similarity tasks because the pointwise mutual information normalization accounts for word frequency.
Given PMI values: (cat, dog)=2.1, (cat, the)=-0.8, (cat, fish)=1.5, (cat, table)=-1.2. Convert to PPMI.
SVD on Co-occurrence Matrices
PPMI rows are long and sparse, one dimension per context word, and synonyms such as "car" and "automobile" may share few non-zero contexts. Truncated SVD factors the matrix as and keeps the top singular values, which by the Eckart-Young theorem gives the best rank- approximation in squared error. Rows of , or of in a common symmetric variant, become dense -dimensional word vectors, and words with similar context profiles land close together even when their raw rows barely overlap. Levy and Goldberg showed that Word2Vec with negative sampling implicitly factorizes a shifted PMI matrix, so SVD of PPMI is a close relative of learned embeddings.
SVD on the PPMI matrix decomposes . Truncating to rank : gives the best rank- approximation (Eckart-Young theorem). Using as word vectors produces -dimensional embeddings. Levy and Goldberg (2014) showed these SVD embeddings are mathematically related to Word2Vec — both implicitly factorize a shifted PMI matrix.
A PPMI matrix has 50,000 rows and 50,000 columns. After SVD with , what are the dimensions of the resulting word vectors?
Theory Exercise
Problem:
The distributional hypothesis states: "You shall know a word by the company it keeps" (Firth, 1957). (a) Explain this in terms of co-occurrence matrices. (b) Give an example of two words that would have similar co-occurrence vectors. (c) Give an example where the distributional hypothesis fails.
Hints:
- Think about what context words reveal about meaning
Coding Exercise
Problem:
Build a word-word co-occurrence matrix with window size 2 from a small corpus. Compute PPMI values and find the most similar word pairs by cosine similarity on the PPMI vectors.
Hints:
- Use nested loops: for each word, look at words within the window
Related Problems on PixelBank
A TF-IDF matrix for about 11,000 newsgroup posts has roughly 39,000 columns, and fewer than 0.2 percent of its entries are non-zero. Two posts about cars can share almost no columns if one says "car" and the other says "automobile". High dimensionality wastes memory, but the bigger problem is that synonyms sit on unrelated axes. Can we find a few dense directions that capture shared meaning?
The previous topic, Co-occurrence Matrices, ended with SVD as a way to compress word-context counts. This topic develops that idea in general. It starts with Principal Component Analysis, which finds orthogonal directions of maximum variance after centering the data. Singular Value Decomposition follows, the factorization underneath PCA that gives the best low-rank approximation of any matrix. Latent Semantic Analysis applies truncated SVD to a term-document matrix, producing topic-like dimensions that partly merge synonyms. The topic closes with truncated SVD for sparse matrices, the iterative and randomized algorithms that make this feasible at scale and that lead into the learned word embeddings of the next chapter.
Definition
Dimensionality reduction maps vectors in to with while preserving as much structure as possible. Linear methods such as PCA and truncated SVD project onto the top singular directions, giving the best rank- approximation in squared error; for text, this turns sparse count vectors into dense latent features.
In this topic
- 1Principal Component Analysis (PCA)
- 2Singular Value Decomposition (SVD)
- 3Latent Semantic Analysis (LSA)
- 4Truncated SVD for Sparse Matrices
Principal Component Analysis (PCA)
PCA finds orthogonal directions, the principal components, along which the data varies most. Center the data by subtracting the mean , compute the covariance matrix, take its top eigenvectors , and project, as in the formula. Each eigenvalue is the variance captured by its component, and the explained variance ratio reports that component's share. For dense data with strongly correlated features, a few components often capture most of the variance, but sparse text behaves differently: on a 20 Newsgroups TF-IDF matrix of about 39,000 terms, 100 SVD components explain only about 11 percent. Centering also destroys sparsity, which is why text pipelines use truncated SVD instead.
The first principal component maximizes the variance of the projected data, , and each later component does the same subject to orthogonality with the earlier ones. The eigenvalue is the variance along , so the explained variance ratio is . How fast that ratio accumulates depends on the data: correlated dense features concentrate variance in a few components, while sparse TF-IDF spreads it widely. On 20 Newsgroups TF-IDF with about 39,000 terms, the top 100 SVD components explain about 11 percent and the top 300 about 21 percent, so choose by downstream accuracy rather than by a variance threshold.
A TF-IDF matrix has 5000 documents and 20,000 features. After PCA, the top 100 components explain 85% of variance. What is the compression ratio? What information is lost?
Singular Value Decomposition (SVD)
SVD factors any matrix as . The columns of are orthonormal directions in document space, the columns of are orthonormal directions in word space, and the diagonal holds non-negative singular values in decreasing order, each measuring the importance of one direction. Keeping the top gives , the best rank- approximation, and the share of squared singular values kept is the share of the matrix's energy retained. Unlike eigendecomposition, SVD works for rectangular matrices and needs no centering. PCA is the SVD of the centered data matrix, and LSA is the SVD of a term-document matrix.
SVD factorizes with singular values . By the Eckart-Young theorem, the rank- truncation minimizes the Frobenius error over all rank- matrices, and that error equals . The share of energy kept is . For singular values 45.2, 23.1, 12.8, 6.3, 2.1, 0.4, and 0.1, keeping two retains 92.5 percent with an error of 14.4. How fast singular values decay depends on the matrix: fast decay means a small suffices, while sparse text matrices decay slowly.
Singular values of a TF-IDF matrix are [45.2, 23.1, 12.8, 6.3, 2.1, 0.4, 0.1]. How many components should you keep to capture 90% of the information?
Latent Semantic Analysis (LSA)
LSA applies truncated SVD to a TF-IDF (or term-frequency) matrix. The resulting low-dimensional space captures latent semantic topics: dimensions no longer correspond to individual words but to abstract concepts. For example, one dimension might capture a "technology" topic (high loading for words like computer, software, algorithm) while another captures "biology" (gene, cell, protein). LSA was one of the first methods to handle synonymy ("car" and "automobile" map to the same latent dimension) and polysemy (multiple senses mapped to different dimensions).
LSA applies SVD to the TF-IDF matrix: . Document vectors are rows of and word vectors are rows of . The truncation merges synonyms: 'car' and 'automobile' that co-occur with similar documents end up with similar vectors even though they never co-occur directly. This latent semantic structure is invisible to raw TF-IDF.
A TF-IDF matrix has documents about sports, politics, and technology. After LSA with k=3, what might the three latent dimensions represent?
Truncated SVD for Sparse Matrices
Full SVD of an matrix costs time and needs the dense matrix in memory, which is impossible for 50,000 documents by 100,000 terms. Truncated SVD computes only the top singular triplets, using Lanczos iteration or randomized range finding (Halko, Martinsson, and Tropp), which touch the matrix only through products with a few vectors. On a sparse matrix each product costs time proportional to the number of non-zeros, so the total work scales roughly with nnz times . scikit-learn's TruncatedSVD accepts sparse input and does not center it, unlike PCA, because centering would fill every zero and destroy sparsity.
Truncated SVD is preferred over full SVD for sparse matrices because it computes only the top singular values/vectors without materializing the full decomposition. Full SVD has complexity ; truncated SVD with randomized algorithms runs in . For , , : full SVD ops, truncated ops — a speedup.
A TF-IDF matrix is 50,000 docs x 100,000 words stored as a sparse matrix with 0.1% non-zero entries. Compare full SVD vs truncated SVD (k=200) in terms of feasibility.
Theory Exercise
Problem:
Compare PCA and truncated SVD for text data. (a) Why is PCA problematic for TF-IDF matrices? (b) What does truncated SVD preserve that full SVD discards? (c) How do you choose the number of components ?
Hints:
- Think about what centering does to a sparse matrix
Coding Exercise
Problem:
Apply truncated SVD to a TF-IDF matrix using scikit-learn. Plot the explained variance ratio and find the optimal that captures 80% of the variance. Then visualize the documents in 2D.
Hints:
- Use TfidfVectorizer for the TF-IDF matrix