Majid Al-RaimiTerm matrices and cosine similarity

ICS 582Lecture 04Part 04

Term matrices and cosine similarity

Building term-document and word-word (term-context) co-occurrence matrices, reading rows and columns as vectors, and measuring similarity with the dot product and its length-normalized form, the cosine.

Concepts
5
Slides
31-44
Reading
30 min
Understood
0/5 concepts

Why this part matters

The previous part said a word is known by the company it keeps. This part turns that slogan into arithmetic: count tables, row and column vectors, and one number, the cosine, that says how alike two vectors are. Every later topic in the lecture stands on it. tf-idf and PPMI reweight these same matrices, word2vec vectors are compared with this same cosine, and the retrievers behind RAG systems and vector databases rank by cosine or by a dot product on normalized vectors.

The argument runs in five steps. First a table of counts over Shakespeare plays, read by columns as documents. Then the same kind of table read by rows as words, and a second table that counts neighbors instead of documents. Then the dot product, the obvious way to compare two rows, and the flaw that makes it reward frequent words. Then the cosine, which removes length and keeps only direction. Finally the full computation for cherry, digital and information by hand, with the slide's one rounding slip flagged.

By the end you can

  1. Build and read a term-document matrix and say what its rows and columns represent.
  2. Explain how a word-word (term-context) matrix is filled from a context window and why it is sparse.
  3. Compute a dot product and a vector length, and explain why the raw dot product favors frequent words.
  4. Derive cosine as the normalized dot product and state its range, including why counts give 0 to 1.
  5. Compute cos(cherry, information) and cos(digital, information) by hand and interpret them as angles.

Documents as columns of counts

Take four Shakespeare plays and four words, and count. As You Like It uses battle once, good 114 times, fool 36 times and wit 20 times. Twelfth Night has no battle at all but 58 fools. Julius Caesar and Henry V, the two histories, have almost no fools and plenty of battles. Put the counts in a grid with one row per word and one column per play, and you already have a usable representation of each play.

WordAs You Like ItTwelfth NightJulius CaesarHenry V
battle10713
good114806289
fool365814
wit201523
Counts of four words in four plays (SLP ch 11, figure 11.4). Read each column as one document.

This grid is a Term-document matrix. In general it has |V| rows, one per word in the vocabulary, and |D| columns, one per document, and the cell in row w and column d counts how often w occurs in d. Each column is then a list of |V| numbers: a vector. As You Like It becomes [1, 114, 36, 20], a point in a 4-dimensional space whose axes are the words. This is the basic move of Vector semantics, applied first to documents rather than words.

Each play as a column vector over (battle, good, fool, wit)

As You Like It (comedy)
[1, 114, 36, 20]
Twelfth Night (comedy)
[0, 80, 58, 15]
Julius Caesar (history)
[7, 62, 1, 2]
Henry V (history)
[13, 89, 4, 3]

Notice what was thrown away. The counts do not record where in the play a word appeared, or what came before it. A document reduced to word frequencies with order discarded is a bag of words, and it is the oldest representation in information retrieval. It sounds crude, but for the question "what is this document about?" it is surprisingly strong, because topic is carried mostly by which words occur and how often.

Seeing the vectors

Four dimensions cannot be drawn, so pick two: fool on the horizontal axis and battle on the vertical one. The comedies become long arrows lying almost flat along fool (As You Like It at [36, 1], Twelfth Night at [58, 0]), while the histories become short arrows pointing up along battle (Julius Caesar at [1, 7], Henry V at [4, 13]). Comedies point one way, histories another. That is the whole promise of the vector view: similar documents have similar columns, so they point in similar directions.

Gerard Salton turned this picture into the vector space model of information retrieval: represent every document and every query as a vector of term weights, measure how close the query vector is to each document vector, and return the closest documents first (Salton, Wong and Yang 1975). A web search for "battle" is, in this model, a vector with a single non-zero entry, and Henry V wins because its column leans hardest in that direction. The measure of closeness is the cosine you will meet in concept 4. Here is a preview of what it says about the plays, computed once on the two plotted dimensions and once on all four.

Pairfool and battle onlyAll four words
As You Like It and Twelfth Night0.99960.95
Julius Caesar and Henry V0.9880.999
As You Like It and Julius Caesar0.1690.945
Twelfth Night and Julius Caesar0.1410.809
Cosine between plays: on the fool and battle plane, and on all four word dimensions

On the plane, the pattern is crisp: comedies with comedies near 1, comedy with history near 0.15. On all four dimensions every pair lands between about 0.81 and 0.999, and As You Like It looks 0.945 similar to Julius Caesar. The culprit is good: it is frequent in every play, so it dominates every vector and makes all of them point roughly the same way. A word that occurs everywhere carries no information about which document you are in, and the next part's tf-idf exists precisely to turn its weight down.

Recall

Why does As You Like It look 0.945 similar to Julius Caesar on all four words, but only 0.169 on fool and battle?

good is frequent in every play, so it dominates all four vectors and points them the same way. Keeping only fool and battle removes good (and wit) and exposes the comedy and history split (0.169 against 0.945); tf-idf down-weights such words instead of dropping them.

Turn the same Shakespeare table sideways and read it by rows. battle becomes [1, 0, 7, 13]: a word that shows up a little in the comedies and a lot in Julius Caesar and Henry V. fool becomes [36, 58, 1, 4], the opposite profile. Without any dictionary, the rows already say that battle is a history word and fool is a comedy word, and two words with similar rows occur in similar documents.

One table, two kinds of vector. The Julius Caesar column lights up as a document vector, then the fool row as a word vector.

Counting neighbors instead of documents

Documents are a coarse unit of context. A play contains thousands of words, so two words sharing a play says little more than that they share a topic. The finer alternative is to count, for each target word, which words appear right next to it. Slide the target through a large corpus, and every time it occurs, look at the words within a fixed window on each side (SLP uses ±4) and add 1 to the cell for each of them.

A ±4 window around cherry. Every word inside the bracket is a context, and each one adds 1 to its cell in cherry's row.

The result is a Term-context matrix, also called a word-word or word-context matrix. It is square, |V| x |V|: rows are target words, columns are context words, and the cell (w, c) counts how often c appeared inside the window around w. Here are four rows from Wikipedia counts, restricted to five of the context columns.

Targetcomputerdataresultpiesugar
cherry28944225
strawberry0016019
digital167016838554
information33253982378513
Co-occurrence counts from Wikipedia (SLP ch 5, figure 5.3), five context columns out of |V|

The rows sort themselves into two families. cherry and strawberry have their mass in pie and sugar; digital and information have theirs in computer and data. Plot digital at [1683, 1670] and information at [3982, 3325] on the data and computer axes and the two arrows point almost the same way, about 5° apart, even though information is more than twice as long. That is the Distributional hypothesis made concrete: two words are similar when their context vectors are similar. Each row is an Embedding of its word, a sparse one built by counting, which later parts will reweight and then replace with short dense vectors.

Ahead of concept 4, here is what the cosine, a 0 to 1 score of how closely two rows point the same way, says about these rows.

PairCosineWhy
cherry and strawberry0.969Both live in the pie and sugar columns
digital and information0.996Both live in the computer and data columns
cherry and digital0.019Almost no shared mass
strawberry and information0.003Almost no shared mass
Cosines on all five context columns (computed for this page; concept 5 uses only pie, data and computer, so its values differ slightly, for example 0.018 instead of 0.019 for cherry and digital)

Two practical facts follow from the shape. First, almost every cell is zero: most of the |V| words never appear within four words of cherry. These are sparse vectors, and real systems store only the non-zero entries (a compressed sparse row format in SciPy, for example). Second, |V| is not the full vocabulary of the corpus. SLP notes that it is usually the 10,000 to 50,000 most frequent words, and that keeping more than about 50,000 rarely helps (SLP 5.3).

MatrixShapeCellSimilarity it captures
Term-document|V| x |D|Count of the word in the documentTopical: which texts a word appears in
Word-word (term-context)|V| x |V|Count of the context word in a window around the targetCloser, more substitutable similarity
The two count matrices of this part

Recall

What are the rows and columns of a term-document matrix, and of a term-context matrix?

Term-document: |V| word rows by |D| document columns, each cell the count of the word in the document. Term-context: |V| x |V|, each cell the count of the context word inside the target's window.

Quick check

A term-document matrix over 37 plays and 20,000 word types has which shape?

Which word is closer to fool: good or wit? Multiply the Shakespeare rows entry by entry and add. For good and fool that gives 9162; for fool and wit only 1604. By this measure good is almost six times closer to fool than wit is, which is clearly wrong: wit and fool are both comedy words, while good is just everywhere.

The measure is the Dot product, the most natural way to compare two vectors:

v⋅w=∑i=1Nviwi=v1w1+v2w2+⋯+vNwN\begin{aligned} \mathbf{v}\cdot\mathbf{w} &= \sum_{i=1}^{N} v_i w_i \\ &= v_1 w_1 + v_2 w_2 + \dots + v_N w_N \end{aligned}
Dot product (SLP eq 5.7)

It is large when both vectors have large values in the same dimensions, so it does behave like a similarity measure. Vectors whose non-zero entries sit in different dimensions get 0: they are orthogonal, which for count vectors means the two words never share a context. The trouble is that a product of two numbers grows with either number. The dot product therefore depends on how big the vectors are, and the size of a vector is its Vector length:

∣v∣=∑i=1Nvi2|\mathbf{v}| = \sqrt{\sum_{i=1}^{N} v_i^2}
Vector length, the Euclidean norm (SLP eq 5.8)

Worked example

Why good beats wit as fool's neighbor

  1. The rows

    good [114, 80, 62, 89], fool [36, 58, 1, 4], wit [20, 15, 2, 3] over (As You Like It, Twelfth Night, Julius Caesar, Henry V).
  2. Dot products

    good · fool = 114×36 + 80×58 + 62×1 + 89×4 = 4104 + 4640 + 62 + 356 = 9162. fool · wit = 36×20 + 58×15 + 1×2 + 4×3 = 720 + 870 + 2 + 12 = 1604.
  3. Lengths

    |good| = √31161 ≈ 176.5, |fool| = √4677 ≈ 68.4, |wit| = √638 ≈ 25.3. good is seven times longer than wit simply because it is a more frequent word.
  4. Divide out the lengths

    9162 / (176.5 × 68.4) ≈ 0.759 and 1604 / (68.4 × 25.3) ≈ 0.929.
  5. Result

    The raw dot product ranks good first, only because good is long. Once length is divided out, wit is the closer neighbor (0.929 against 0.759), which matches intuition. That division is the cosine of the next concept.

The general lesson is SLP's: the dot product favors long vectors, and more frequent words have longer vectors, because they co-occur with many words and do so many times. Words such as of, the and you would therefore come out as the nearest neighbor of almost everything. Information retrieval met the same problem with documents: a long document has larger counts everywhere, and a raw dot product with a query rewards it for being long rather than for being on topic (Manning, Raghavan and Schütze, "Dot products").

Recall

Why does the raw dot product favor frequent words?

Frequent words co-occur with many words at high counts, which makes their vectors long. The dot product grows with the lengths of the vectors, so long vectors score high against almost everything.

Cosine: the length-normalized dot product

Run an experiment on digital. Suppose the corpus were twice as large, so every count in its row doubles, from [5, 1683, 1670] to [10, 3366, 3340] over (pie, data, computer). Its dot product with information doubles too, from 12,254,481 to 24,508,962. Nothing about the meaning of digital changed, yet the similarity score did. The cure is to measure the angle between the vectors rather than their overlap, and the angle does not move at all.

Geometry supplies the formula. For any two vectors, the dot product equals the product of their lengths times the cosine of the angle θ between them. Solve for the cosine and you get Cosine similarity:

a⋅b=∣a∣ ∣b∣cos⁡θ⟹cos⁡(v,w)=v⋅w∣v∣ ∣w∣=v∣v∣⋅w∣w∣=∑i=1Nviwi∑i=1Nvi2 ∑i=1Nwi2\begin{aligned} \mathbf{a}\cdot\mathbf{b} &= |\mathbf{a}|\,|\mathbf{b}|\cos\theta \\ \Longrightarrow\quad \cos(\mathbf{v},\mathbf{w}) &= \frac{\mathbf{v}\cdot\mathbf{w}}{|\mathbf{v}|\,|\mathbf{w}|} \\ &= \frac{\mathbf{v}}{|\mathbf{v}|}\cdot\frac{\mathbf{w}}{|\mathbf{w}|} \\ &= \frac{\sum_{i=1}^{N} v_i w_i}{\sqrt{\sum_{i=1}^{N} v_i^2}\,\sqrt{\sum_{i=1}^{N} w_i^2}} \end{aligned}
Cosine similarity in three equivalent forms (SLP eqs 5.9 and 5.10)

The middle form is the useful one to remember. Dividing a vector by its own length gives a unit vector, a vector of length 1 pointing the same way: [3, 4] has length 5, so its unit vector is [0.6, 0.8], and 0.6² + 0.8² = 1. The cosine is simply the dot product of the two unit vectors. Length has been removed before the comparison, so only direction is left.

Stretch v to 2v along the same ray: the dot product doubles, the cosine stays where it was.

Three properties follow. The range is -1 to 1: 1 for vectors pointing the same way, 0 for orthogonal vectors, -1 for opposite directions. Scaling is invisible: for any c > 0, cos(cv, w) = cos(v, w), because the c appears once in the numerator and once in |cv| = c|v| and cancels (SLP exercise 5.2). And for raw counts the range shrinks to 0 to 1, because no count is negative.

This is also why real systems often skip the division at query time. If every stored vector is normalized to length 1 once, in advance, then a plain dot product is the cosine. scikit-learn documents exactly this: cosine_similarity is the normalized dot product, and on L2-normalized data it is equivalent to linear_kernel. Vector databases that offer an "inner product" metric rely on the same identity, and it is why the embedding vectors of many retrieval models come out already normalized.

Recall

Compute cos([1, 0], [1, 1]).

Numerator 1×1 + 0×1 = 1. Lengths 1 and √2. Cosine 1 / √2 ≈ 0.707, an angle of 45°.

Recall

What happens to cos(v, w) if v is multiplied by 3? And for unit vectors, how do the dot product and the cosine relate?

Nothing happens: the 3 multiplies the numerator and |v| equally and cancels. For unit vectors the denominator is 1 × 1, so the dot product and the cosine are equal.

Quick check

Why do we divide the dot product by the two vector lengths?

Quick check

For raw co-occurrence count vectors, what range can the cosine take?

Now do the whole computation once by hand, on three words and three context dimensions (pie, data, computer): cherry [442, 8, 2], digital [5, 1683, 1670] and information [5, 3982, 3325]. The question is which of cherry and digital is closer to information under the cosine.

Worked example

cos(cherry, information) and cos(digital, information)

  1. Lengths

    |cherry| ≈ 442.08, |digital| ≈ 2370.95, |information| ≈ 5187.68. Each is the length, the square root of the sum of squared counts.
  2. cherry and information

    Dot product (numerator) 442×5 + 8×3982 + 2×3325 = 2210 + 31856 + 6650 = 40716. Cosine 40716 / (442.08 × 5187.68) ≈ 0.0178, an angle of about 89.0°.
  3. digital and information

    Numerator 5×5 + 1683×3982 + 1670×3325 = 25 + 6701706 + 5552750 = 12254481. Cosine 12254481 / (2370.95 × 5187.68) ≈ 0.9963, an angle of about 4.9°.
  4. Result

    cos(digital, information) ≈ 0.996 and cos(cherry, information) ≈ 0.018. digital is almost exactly aligned with information; cherry is nearly at a right angle to it. For completeness, cos(cherry, digital) ≈ 0.018 as well.

Every intermediate quantity, for checking your own arithmetic

|cherry|
√(442² + 8² + 2²) = √195432 ≈ 442.08
|digital|
√(5² + 1683² + 1670²) = √5621414 ≈ 2370.95
|information|
√(5² + 3982² + 3325²) = √26911974 ≈ 5187.68
cherry · information
442×5 + 8×3982 + 2×3325 = 2210 + 31856 + 6650 = 40716
digital · information
5×5 + 1683×3982 + 1670×3325 = 25 + 6701706 + 5552750 = 12254481
cos(cherry, digital)
≈ 0.018

The picture makes the numbers obvious. Plot the words on two of the dimensions, pie upward and computer to the right. cherry stands nearly upright, because nearly all of its mass is in pie. digital and information both lie almost flat along computer. The angle between cherry and information is close to a right angle, so its cosine is close to 0; the angle between digital and information is a sliver, so its cosine is close to 1.

Schematic of slide 44 (angles widened so the small one is visible): a wide arc between cherry and information, a sliver between digital and information. Small angle, large cosine.

Recall

Without a calculator, why must cos(cherry, information) be small?

cherry's mass is in pie and information's is in data and computer. The large counts never meet in the same dimension, so the numerator is tiny compared with the product of the lengths.

Quick check

Using counts over (pie, data, computer), which word is closest to information?

Recap

If you remember nothing else

  • A term-document matrix is |V| x |D|: columns are document vectors, and rows are word vectors over documents.
  • A word-word (term-context) matrix is |V| x |V| and counts context words in a window such as ±4. Its rows are sparse word vectors.
  • The dot product Σ v_i w_i is high when both vectors are large in the same dimensions, but it grows with vector length, so frequent words win.
  • Cosine = v·w / (|v||w|) is the dot product of unit vectors. It ignores length and measures only the angle.
  • Cosine runs from -1 to 1 in general and from 0 to 1 for counts. It is unchanged by scaling a vector by a positive number.
  • Worked example: cos(digital, information) ≈ 0.996 and cos(cherry, information) ≈ 0.018 (the slide's .017 is a rounding slip).

Sources