The Math Behind the Machine/ Unit 16 · Words as Vectors Checks 0/43
Unit 16 of 20 · by Prof. Saurabh

Words as Vectors

A computer cannot read: to it, a word is just a label, like a code number in a shopkeeper's register. In this unit we give every word a place on a map of meaning — a short list of numbers — so that words used alike live close together. First we count: guess the next word from the words before it, then weigh and squeeze the company words keep. Then we stop counting and start predicting: word2vec's two games, CBOW and skip-gram, learn the map by filling in blanks and guessing neighbours — and turn out to be counting in disguise. At the end, meaning is a direction: king − man + woman lands next to queen.

≈ 150 min read + play · five acts 23 interactive widgets · 5 in 3D · an embedding explorer to come back to 43 inline checks 🧾 30 proofs, folded away — open "if you want the algebra" when you are ready ✍ 16 solved practice problems

← Unit 15 · The Network, Whole

a word is where it lives · drag to orbit
1

A word is just a label

How could a computer ever know that chai is like coffee?

Imagine this

A new shopkeeper opens a stock register. He gives every item a code number: 1 is chai, 2 is coffee, 3 is a cricket bat.

Is 2 "closer" to 1 than 3 is? No. The numbers are just labels. They say nothing about what the items are. Chai and coffee are both hot drinks, but the register cannot know that.

A computer sees words the same way. To a computer, "chai" is just a label. Our job in this unit is to turn every word into numbers that carry its meaning.

First, what counts as a word? Before a computer can count anything, it cuts the text into pieces called tokens. Often everything is lower-cased first, so that "Chai" and "chai" count as one word. Punctuation becomes a token of its own. And we add two markers to every sentence: ⟨s⟩\langle s\rangle at the start and ⟨/s⟩\langle/s\rangle at the end. They mean "a sentence starts here" and "a sentence stops here", and §2 will need them. So I drink chai. becomes

<s> I drink chai . </s>

(We keep "I" as a capital so the examples read naturally.) Modern language models go one step further and cut rare words into smaller pieces; §16 shows how.

Now the simplest way to turn a word into numbers: give each word its own slot. Take a tiny vocabulary of three words — chai, coffee, cricket. Each word becomes a list of three numbers with a single 1 in its own slot:

chai=(1,0,0),coffee=(0,1,0),cricket=(0,0,1).\begin{aligned}\text{chai}&=(1,0,0),\\ \text{coffee}&=(0,1,0),\\ \text{cricket}&=(0,0,1).\end{aligned}

A list of zeros with a single 1 is called a one-hot vector. With a real vocabulary of 50 000 words, each list is 50 000 numbers long: one 1 and 49 999 zeros.

Now measure how alike two words are, the way Unit 3 taught us: with the dot product. Multiply slot by slot and add:

chai⋅coffee=1⋅0+0⋅1+0⋅0=0.\text{chai}\cdot\text{coffee}=1\cdot0+0\cdot1+0\cdot0=0.

Chai with cricket? Also 0. Every pair of different one-hot words has dot product 0: they all stand at right angles to each other. And every pair is the same distance apart: 12+12=2≈1.414\sqrt{1^2+1^2}=\sqrt2\approx1.414. In one-hot land, chai is exactly as far from coffee as it is from cricket.

The picture to keep: a phone directory and a city map

A phone directory gives every person a line of their own. It tells you who exists, but not who lives near whom. One-hot lists are a directory: every word on its own line, every pair equally far apart, no neighbourhoods.

A city map is different. People who live near each other are drawn near each other, and a neighbourhood has a character — the market, the stadium, the station. We want a map of words: tea words in one neighbourhood, cricket words in another, so that on the map close means similar. This whole unit is about turning the directory into the map.

From a directory to a mapOne-hot land puts each word on its own axis, all at right angles. In "meaning" land the lists are free, so words that are used alike can lean together. (The "meaning" arrows here are hand-made, to show the idea.)

Try: Start in one-hot land and read the three distances: all the same, 1.414. Then press ▶ let meaning pull and watch chai and coffee lean together (cosine 0.91) while cricket stays apart. Drag the picture to look from the side.

drag the picture to orbit

Trap

Why not just number the words 1, 2, 3, like the shopkeeper? Because that is worse than one-hot: it invents an order that isn't there. The computer would believe coffee (2) sits halfway between chai (1) and cricket (3), and that chai + cricket = 2 × coffee. One-hot at least tells no lies — it just tells nothing.

The realization

ei⋅ej=0,∥ei−ej∥=2(i≠j)\begin{gathered}\mathbf e_i\cdot\mathbf e_j=0,\\ \lVert\mathbf e_i-\mathbf e_j\rVert=\sqrt2\quad(i\ne j)\end{gathered}

One-hot lists put every word at right angles to every other word, all the same distance apart. They tell words apart, but they cannot say "these two are alike". We want short lists where close means similar. The rest of this unit is about finding them.

Pause & predict

With a vocabulary of 10 000 words written one-hot, what is the dot product of "chai" and "coffee", and how far apart are they?

Pause & predict

The shopkeeper adds a fourth word, "tea", to the one-hot vocabulary. Which of the old words does tea land closest to?

If you want the algebra · 1 proof, step by step
Prove it · every pair of one-hot words is √2 apart

Claim. For one-hot vectors ei\mathbf e_i and ej\mathbf e_j with i≠ji\ne j: ei⋅ej=0\mathbf e_i\cdot\mathbf e_j=0 and ∥ei−ej∥=2\lVert\mathbf e_i-\mathbf e_j\rVert=\sqrt2, whatever the vocabulary size VV.

1
The dot product adds VV products, one per slot. In every slot at least one of the two lists has a 0, because their single 1s sit in different slots. So every product is 0 and the sum is 0. Right angles: the cosine is 0 too.
2
The difference ei−ej\mathbf e_i-\mathbf e_j has +1+1 in slot ii, −1-1 in slot jj and 0 elsewhere. So ∥ei−ej∥2=12+(−1)2=2.\begin{aligned}&\lVert\mathbf e_i-\mathbf e_j\rVert^2\\ &=1^2+(-1)^2=2.\end{aligned} ∎ Or use ∥a−b∥2=∥a∥2+∥b∥2−2 a⋅b=1+1−0\lVert\mathbf a-\mathbf b\rVert^2=\lVert\mathbf a\rVert^2+\lVert\mathbf b\rVert^2-2\,\mathbf a\cdot\mathbf b=1+1-0.

The road ahead. The unit has five acts.

  1. A word is just a label (§1) — the directory we start from.
  2. Guessing the next word by counting (§2–§4): a sentence as a chain of guesses, what to do about words never seen, and how to score a guesser by its surprise — its perplexity.
  3. Meaning from the company a word keeps (§5–§7): count the company, weigh it (TF-IDF and PMI), and squeeze it with the SVD from Unit 5.
  4. Stop counting, start predicting (§8–§14): word2vec's two games, CBOW and skip-gram; how to make them cheap; why counting and predicting arrive at the same answer; and a small neural language model.
  5. The geometry of meaning, and its limits (§15–§17): king − man + woman, words with two meanings, words cut into pieces, and the road to Units 17 and 18.

In one sentence: A one-hot list is a phone directory — every word on its own line, every pair at right angles and 2\sqrt2 apart — so it names words but carries no meaning; we want a city map, where close means similar.

2

A sentence is a chain of guesses

How does your phone's keyboard know what you are about to type?

Imagine this

You type "good" and the keyboard offers "morning". It has seen you — and millions of others — type "good morning" again and again. It simply remembers what usually comes next.

Now play a game with a friend. You say a sentence one word at a time, and before each word she guesses what comes next. "I…" — "drink?" — "drink…" — "chai?" A whole sentence is just a chain of guesses.

That game is exactly how a language model scores a sentence. The chance of the whole sentence is the chance of the first word, times the chance of the second word given the first, times the chance of the third given the first two, and so on. This is the chain rule of probability:

P(w1w2w3⋯wn)=P(w1) P(w2∣w1) P(w3∣w1w2)⋯\begin{aligned}&P(w_1w_2w_3\cdots w_n)\\ &=P(w_1)\,P(w_2\mid w_1)\,P(w_3\mid w_1w_2)\cdots\end{aligned}

Read it aloud: a sentence is a string of guesses, and each guess is allowed to use everything that came before it. Nothing is approximated yet. The rule is exact.

The trouble is the history. To know the chance of chai after every morning my grandfather drinks a hot cup of, we would need to have seen that exact history many times. Long histories almost never repeat, so we cannot count them.

So we make a bold simplification, called the Markov assumption: the guesser keeps only the last few words and forgets the rest. It is a guesser with a short memory. If it remembers one word, it is a bigram model ("bi" = two words at a time); if it remembers two, a trigram model; in general, remembering N−1N-1 words makes an N-gram model:

P(chai∣I drink)≈P(chai∣drink).P(\text{chai}\mid\text{I drink})\approx P(\text{chai}\mid\text{drink}).

Now count. Here is a tiny collection of text — people call such a collection a corpus — with the sentence markers added:

<s> I drink chai </s> · <s> I drink coffee </s> · <s> I drink chai </s> · <s> I play cricket </s>

"drink" is followed by chai twice and by coffee once. So the best guess for what follows "drink" is to split the chances the same way:

P(chai∣drink)=count(drink chai)count(drink)=23,P(coffee∣drink)=13.\begin{aligned}P(\text{chai}\mid\text{drink})&=\frac{\text{count}(\text{drink chai})}{\text{count}(\text{drink})}\\ &=\frac23,\\ P(\text{coffee}\mid\text{drink})&=\frac13.\end{aligned}

This "count ÷ total" is not a guess about guessing. It is the maximum-likelihood answer of Unit 14: a coin that showed 7 heads in 10 tosses is best described by p=7/10p=7/10, and a word followed by chai 2 times out of 3 is best described by 2/32/3.

Now score a whole sentence by multiplying the guesses along the chain. The start marker gives the first word a history too: its guess is P(I∣⟨s⟩)P(\text{I}\mid\langle s\rangle), "how often does a sentence start with I?"

P(⟨s⟩ I drink chai ⟨/s⟩)=P(I∣⟨s⟩) P(drink∣I)⋅P(chai∣drink) P(⟨/s⟩∣chai)=1⋅34⋅23⋅1=12.\begin{aligned}&P(\langle s\rangle\ \text{I drink chai}\ \langle/s\rangle)\\ &=P(\text{I}\mid\langle s\rangle)\,P(\text{drink}\mid\text{I})\\ &\quad\cdot P(\text{chai}\mid\text{drink})\,P(\langle/s\rangle\mid\text{chai})\\ &=1\cdot\tfrac34\cdot\tfrac23\cdot1=\tfrac12.\end{aligned}

Why the end marker matters. ⟨/s⟩\langle/s\rangle is a word the model must guess, so the model learns when to stop. Without it, the half-sentence "I drink" would score 34\tfrac34 — more than any complete sentence — and the chances of all sentences would add up to more than 1. With it, every sentence must pay for its ending, and the chances of all possible sentences add up to exactly 1.

And the model can write. Start at ⟨s⟩\langle s\rangle, roll a loaded die whose faces are the next words and whose weights are their chances, write down the face, and repeat until ⟨/s⟩\langle/s\rangle comes up. Claude Shannon wrote sentences this way, by hand, in 1948.

A guesser with a short memoryThe corpus on the left (the markers <s> and </s> are added to every line for you). The table counts what follows each history; the bars show the guess for the chosen history; the chain multiplies the guesses along a sentence.

Try: Press ▶ play the chain and watch "<s> I drink chai </s>" collect 1 · ¾ · ⅔ · 1 = 0.5, one lit cell at a time. Pick "drink" to read ⅔ and ⅓. Add the line we drink coffee: with a memory of one word, "drink" now splits ½ · ½; switch the memory to two words and "I drink" still prefers chai while "we drink" is sure of coffee. Then press ✎ write a sentence a few times.

…
the guesser's memory
after
Why does this work?

Because language repeats itself. The same short chains of words — "drink chai", "play cricket", "good morning" — come back again and again, so their counts are reliable even when whole sentences never repeat. Cutting the memory to one or two words trades a little accuracy for counts we can actually trust.

Trap

A bigram model has no idea what came two words back. In "The train to Delhi from platform four is ___", it sees only "is" — the train, Delhi and the platform are all forgotten. Every bit of memory you give up is context the model can never use. (Units 17 and 18 are about getting that memory back.)

The realization

P(w1⋯wn)=∏tP(wt∣w1⋯wt−1),P(wt∣wt−1)≈count(wt−1 wt)count(wt−1)\begin{gathered}P(w_1\cdots w_n)\\ =\prod_{t}P(w_t\mid w_1\cdots w_{t-1}),\\ P(w_t\mid w_{t-1})\approx\frac{\text{count}(w_{t-1}\,w_t)}{\text{count}(w_{t-1})}\end{gathered}

A sentence is a chain of guesses. The chain rule is exact; the Markov assumption shortens each guess's memory so that we can count; counting is the maximum-likelihood guess; and the markers ⟨s⟩\langle s\rangle, ⟨/s⟩\langle/s\rangle let the chain start and stop.

Pause & predict

With the four-sentence corpus, what probability does the bigram model give to ⟨s⟩\langle s\rangle I play cricket ⟨/s⟩\langle/s\rangle?

Pause & predict

The bigram model reads "you drink" — and "you" never appears in its corpus. What does it guess for the next word?

If you want the algebra · 2 proofs, step by step
Prove it · the chain rule is "and then", again and again

Claim. For any three words, P(w1w2w3)=P(w1) P(w2∣w1) P(w3∣w1w2)P(w_1w_2w_3)=P(w_1)\,P(w_2\mid w_1)\,P(w_3\mid w_1w_2) — and the same peeling works for any number of words.

1
"The chance of BB given AA" means: of all the times AA happens, the share in which BB happens too (Unit 14). So P(A and B)=P(A) P(B∣A).\begin{aligned}&P(A\text{ and }B)\\ &=P(A)\,P(B\mid A).\end{aligned} First AA must happen, and then BB must happen given AA.
2
Take AA = "the sentence starts w1w2w_1w_2" and BB = "the third word is w3w_3": P(w1w2w3)=P(w1w2)⋅P(w3∣w1w2).\begin{aligned}&P(w_1w_2w_3)\\ &=P(w_1w_2)\\ &\quad\cdot P(w_3\mid w_1w_2).\end{aligned} Peel off the last word.
3
Peel again: P(w1w2)=P(w1) P(w2∣w1)P(w_1w_2)=P(w_1)\,P(w_2\mid w_1). Put the two together. ∎ No approximation anywhere. The Markov assumption comes after this, when we shorten each history.
Prove it · count ÷ total is the best guess

Claim. After a word ww, the next words were seen with counts c1,…,cVc_1,\dots,c_V (total nn). The probabilities p1,…,pVp_1,\dots,p_V that make the seen text most likely are pj=cj/np_j=c_j/n.

1
The text's probability contains pjp_j once for every time word jj followed ww. Take the log (Unit 14's likelihood): ℓ= c1ln⁡p1+…+cVln⁡pV.\begin{aligned}\ell=\ &c_1\ln p_1+\dots\\ &+c_V\ln p_V.\end{aligned} Maximise ℓ\ell with the rule p1+⋯+pV=1p_1+\dots+p_V=1.
2
Add a Lagrange multiplier λ\lambda for the rule and set each slope to zero: cjpj−λ=0 ⇒ pj=cjλ.\frac{c_j}{p_j}-\lambda=0\ \Rightarrow\ p_j=\frac{c_j}{\lambda}. The Lagrange recipe of Unit 11: one extra number for the rule, then every slope is zero.
3
The rule ∑pj=1\sum p_j=1 gives λ=∑cj=n\lambda=\sum c_j=n. So pj=cj/np_j=c_j/n. ∎ With our corpus: after "drink" the counts are chai 2, coffee 1, so p=(2/3, 1/3)p=(2/3,\,1/3).

In one sentence: A sentence is a chain of guesses — the chain rule multiplies them exactly, the Markov assumption gives the guesser a short memory so we can count, and count ÷ total (with <s> and </s>) gives <s> I drink chai </s> the chance 1 · ¾ · ⅔ · 1 = ½.

3

Never seen is not impossible: smoothing

If two words never appeared side by side in our text, is that pair really impossible?

Imagine this

A new chaiwala opens a stall near your office. You have never bought tea from him. Does that make it impossible that you ever will? Of course not.

"Never seen" is not "impossible". A counting model has to learn that lesson.

The zero problem. What does our bigram model say about "I drink cricket"? The pair "drink cricket" was never counted, so its chance is 0 — and one zero in the chain makes the whole sentence 0. With real text most possible pairs are never seen, so this happens all the time. Worse, in §4 a single zero will make the model's score infinitely bad.

Fix 1 · one free ticket for every pair. Pretend every possible next word was seen one extra time. This is add-one (or Laplace) smoothing. After "drink" the possible next words are the 7 words that can come next — I, drink, chai, coffee, play, cricket and ⟨/s⟩\langle/s\rangle — so the row gains 7 extra counts:

P(chai∣drink)=2+13+7=0.3,P(cricket∣drink)=0+13+7=0.1.\begin{aligned}P(\text{chai}\mid\text{drink})&=\frac{2+1}{3+7}=0.3,\\ P(\text{cricket}\mid\text{drink})&=\frac{0+1}{3+7}=0.1.\end{aligned}

No zeros any more. The price: the words we really saw lost some of their share. Chai fell from 0.667 to 0.3.

Trap

With a real vocabulary, add-one gives away almost everything. With V=50 000V=50\,000 possible next words, the row for "drink" gets 50 000 free tickets and only 3 real ones:

P(chai∣drink)=2+13+50 000≈0.00006.\begin{aligned}&P(\text{chai}\mid\text{drink})\\ &=\frac{2+1}{3+50\,000}\approx0.00006.\end{aligned}

The two real sightings are drowned. Almost all the probability now sits on words that never once followed "drink".

Fix 2 · smaller tickets. Give each unseen pair a fraction kk of a ticket instead of a whole one: P=c+kn+kVP=\dfrac{c+k}{n+kV}, called add-kk. It helps, but somebody has to choose kk.

Fix 3 · ask several advisers. Planning a trip, you might ask a friend who went there last month (specific, but little experience) and a travel agent (general, but lots of experience), and blend their advice. Interpolation does the same with a trigram, a bigram and a unigram model (which ignores the history and just knows how common each word is), mixing their guesses with weights that add up to 1.

Worked example: blend the bigram with weight 0.8 and the unigram with weight 0.2. The unigram adviser counts every token that can come next — everything except the ⟨s⟩\langle s\rangle markers, 16 tokens in all: I 4, drink 3, chai 2, coffee 1, play 1, cricket 1, ⟨/s⟩\langle/s\rangle 4. So

P(chai∣drink)=0.8⋅23+0.2⋅216=0.5583,P(cricket∣drink)=0.8⋅0+0.2⋅116=0.0125.\begin{aligned}&P(\text{chai}\mid\text{drink})\\ &\quad=0.8\cdot\tfrac23+0.2\cdot\tfrac{2}{16}=0.5583,\\ &P(\text{cricket}\mid\text{drink})\\ &\quad=0.8\cdot0+0.2\cdot\tfrac{1}{16}=0.0125.\end{aligned}

Cricket is no longer impossible, and chai still leads by far.

Fix 4 · backoff. Ask the specialist first. If the specialist has never seen this history, back off and ask the generalist: use the trigram if it has counts, else the bigram, else the unigram. (The borrowed chances are scaled down a little so that each row still adds up to 1.)

Where does the probability go?The row for "drink" under four recipes. Hollow bars are the raw counts (count ÷ total). The meter shows how much probability was taken from the words really seen and handed to words never seen.

Try: Press add-one: chai 0.3, cricket 0.1. Now drag the vocabulary up to 50 000 and watch chai sink to 0.00006 while the meter floods orange. Switch to add-k and slide kk down to 0.01. Last, press interpolation and set λ=0.8\lambda=0.8: chai 0.558, cricket 0.0125 — nothing is zero, and every row still adds up to 1.

7
0.1
0.8
Why does this work?

Each fix keeps the row adding up to 1, so probability is never created — only moved. Add-one and add-kk move it evenly to every unseen word, which is fair only when the vocabulary is small. Interpolation moves it where the general evidence points: an unseen pair gets a share in proportion to how common the word is overall, while the history still decides whenever it has something to say.

The realization

Padd-k=c+kn+kV,Pinterp=λ Pbigram+(1−λ) Punigram\begin{gathered}P_{\text{add-}k}=\frac{c+k}{n+kV},\\ P_{\text{interp}}=\lambda\,P_{\text{bigram}}\\ +(1-\lambda)\,P_{\text{unigram}}\end{gathered}

Smoothing moves a little probability from what was seen to what was not, so that "never seen" stops meaning "impossible". Add-one is the simplest move and drowns real counts in a big vocabulary; interpolation and backoff move the probability sensibly, by asking a more general adviser.

Pause & predict

With add-one smoothing (7 possible next words), what is P(coffee∣drink)P(\text{coffee}\mid\text{drink})?

Pause & predict

You keep add-one smoothing, but the vocabulary grows from 7 words to 50 000. What happens to P(chai∣drink)P(\text{chai}\mid\text{drink})?

Pause & predict

In the interpolation λPbigram+(1−λ)Punigram\lambda P_{\text{bigram}}+(1-\lambda)P_{\text{unigram}}, set λ=0\lambda=0. What does the model become?

If you want the algebra · 2 proofs, step by step
Prove it · add-one still adds up to one

Claim. With add-one smoothing, pj=cj+1n+Vp_j=\dfrac{c_j+1}{n+V}, and these VV numbers add up to 1.

1
Add the tops: ∑j=1V(cj+1)=(∑jcj)+V=n+V.\begin{aligned}&\sum_{j=1}^{V}(c_j+1)\\ &=\Big(\sum_j c_j\Big)+V\\ &=n+V.\end{aligned} One extra count for each of the VV possible next words.
2
So ∑jpj=n+Vn+V=1\sum_j p_j=\dfrac{n+V}{n+V}=1, and no pjp_j is zero because every top is at least 1. ∎ After "drink" (n=3n=3, V=7V=7): 310+210+5⋅110=1\tfrac{3}{10}+\tfrac{2}{10}+5\cdot\tfrac{1}{10}=1.
Prove it · a blend of two advisers still adds up to one

Claim. If PbP_b and PuP_u each add up to 1 over the next words, then so does P=λPb+(1−λ)PuP=\lambda P_b+(1-\lambda)P_u for any 0≤λ≤10\le\lambda\le1 — and if λ<1\lambda<1, every word with Pu(w)>0P_u(w)>0 gets a chance above 0.

1
Add the blend over all words and split the sum: ∑wP(w)=λ∑wPb(w)+(1−λ)∑wPu(w)=λ+(1−λ)=1.\begin{aligned}&\sum_wP(w)\\ &=\lambda\sum_wP_b(w)\\ &\quad+(1-\lambda)\sum_wP_u(w)\\ &=\lambda+(1-\lambda)=1.\end{aligned} A weighted average of two lists that add to 1.
2
Both parts are never negative, and the second part is (1−λ)Pu(w)>0(1-\lambda)P_u(w)>0 whenever λ<1\lambda<1 and Pu(w)>0P_u(w)>0. ∎ With λ=0.8\lambda=0.8: P(cricket∣drink)=0.8⋅0+0.2⋅116=0.0125P(\text{cricket}\mid\text{drink})=0.8\cdot0+0.2\cdot\tfrac1{16}=0.0125. Not zero, because the generalist has seen cricket.

In one sentence: Smoothing moves a little probability from pairs we saw to pairs we didn't — add-one does it evenly and drowns real counts in a big vocabulary (3/50 003), while interpolation and backoff ask a more general adviser (0.8 · ⅔ + 0.2 · 2/16 = 0.558).

4

How surprised is the model? Perplexity

Two keyboards both guess your next word. How do you decide which one is better?

Imagine this

At the railway station the speaker says: "The train to Delhi is running…". Before the next word comes, you already guess "late". If it is "late", you are not surprised at all. If it is "early", you are very surprised.

A good language model is one that is rarely surprised by real text.

In Unit 14 we measured surprise. If the model gave the word that really came next a probability pp, its surprise is log⁡2(1/p)\log_2(1/p) bits. Probability 12\tfrac12 → 1 bit. Probability 14\tfrac14 → 2 bits. Probability 1 → 0 bits: no surprise at all.

Let a model read four words of real text. It gave the words that really came next these probabilities: 0.5, 0.25, 0.5, 0.1250.5,\ 0.25,\ 0.5,\ 0.125. The surprises are 1, 2, 1 and 3 bits, and the average surprise is

1+2+1+34=1.75 bits.\frac{1+2+1+3}{4}=1.75\text{ bits}.

This average is the cross-entropy of Unit 14. It is hard to feel what "1.75 bits" means, so we turn it back into a number of choices:

21.75≈3.364.2^{1.75}\approx3.364.

This number is the perplexity. Here is the picture to keep: how many sides does the model's die have? On average, this model was as unsure as someone rolling a fair die with about 3.4 faces. Lower is better. A perfect model has perplexity 1 — a die with one face.

Our bigram model scoring ⟨s⟩\langle s\rangle I drink chai ⟨/s⟩\langle/s\rangle made four guesses (I, drink, chai and ⟨/s⟩\langle/s\rangle) whose product was 12\tfrac12. So its perplexity on that sentence is

(12)−1/4=20.25≈1.189.\Big(\tfrac12\Big)^{-1/4}=2^{0.25}\approx1.189.

That is a die with barely more than one face — no surprise, since the model is being tested on a sentence it was counted from.

A model that knows nothing spreads its guess evenly over a vocabulary of VV words and gives every word 1/V1/V. Its surprise is log⁡2V\log_2V every time, so its perplexity is exactly VV: a fair die with VV faces. That is the worst sensible score, and a useful yardstick. A model with perplexity 120 on a 50 000-word vocabulary has narrowed each guess from 50 000 choices to about 120.

Surprise, averaged, turned into a dieSet the probability the model gave to each of four real next words. The bars show each surprise; the spinner shows the perplexity — how many equal slices the model's uncertainty is worth.

Try: Press 0.5 · 0.25 · 0.5 · 0.125: average 1.75 bits, perplexity 3.364. Press our sentence (1, ¾, ⅔, 1): perplexity 1.189. Press no idea (1/6 each): perplexity 6, a fair six-sided die. Then press one bad miss and watch a single word given 0.01 drag the whole score up.

0.5
0.25
0.5
0.125
Why does this work?

Perplexity averages surprises, which are logs, so it is really a geometric mean of the probabilities, turned upside down. That makes it strict: a word the model thought nearly impossible adds a huge surprise that no number of easy words can cancel. A model with low perplexity has to be reasonable about every word, not just most of them — which is also why smoothing (§3) matters so much.

Trap

Perplexities can only be compared on the same test text with the same vocabulary. Children's stories are easier to predict than legal documents, and a model with a 5 000-word vocabulary has a smaller die to begin with than one with 50 000 words. A lower number from a different test is not a better model. And always test on text the model was not counted from — our 1.189 above flatters the model for exactly that reason.

The realization

perplexity=2 1N∑tlog⁡21pt=(∏t=1Npt)−1/N\begin{aligned}\text{perplexity}&=2^{\,\frac1N\sum_{t}\log_2\frac{1}{p_t}}\\ &=\Big(\prod_{t=1}^{N}p_t\Big)^{-1/N}\end{aligned}

Perplexity is the average surprise turned back into a number of equally likely choices — the number of faces on the model's die. It is 1 for a perfect model and VV for a model that guesses evenly over VV words. One word the model thought nearly impossible can ruin it, so a good model never says "impossible".

Pause & predict

A model gives each of four real next words probability 0.5. What is its perplexity?

Pause & predict

A model with no knowledge guesses evenly over a vocabulary of 10 000 words. What is its perplexity on any text?

Pause & predict

Model A scores perplexity 120 on newspaper text. Model B scores 90 on children's stories. Which is the better model?

If you want the algebra · 2 proofs, step by step
Prove it · perplexity is one over the average probability, the geometric way

Claim. 21N∑tlog⁡2(1/pt)=(p1p2⋯pN)−1/N2^{\frac1N\sum_t\log_2(1/p_t)}=\big(p_1p_2\cdots p_N\big)^{-1/N}, and the answer is the same if you use natural logs and ee instead of log⁡2\log_2 and 2.

1
A sum of logs is the log of a product: 1N∑tlog⁡21pt=log⁡2(∏tpt)−1/N.\begin{aligned}&\frac1N\sum_t\log_2\frac1{p_t}\\ &=\log_2\Big(\prod_t p_t\Big)^{-1/N}.\end{aligned} log⁡(xy)=log⁡x+log⁡y\log(xy)=\log x+\log y and klog⁡x=log⁡xkk\log x=\log x^k.
2
Raising 2 to log⁡2(something)\log_2(\text{something}) gives back the something. The same holds with ee and ln⁡\ln, so the base does not matter. ∎ Check: (0.5⋅0.25⋅0.5⋅0.125)−1/4=(1/128)−1/4=1281/4≈3.364(0.5\cdot0.25\cdot0.5\cdot0.125)^{-1/4}=(1/128)^{-1/4}=128^{1/4}\approx3.364.
Prove it · guessing evenly gives perplexity V

Claim. A model that gives every one of VV words probability 1/V1/V has perplexity exactly VV on any text.

1
Every word, whatever it is, gets pt=1/Vp_t=1/V. So the product of NN of them is V−NV^{-N}. The model does not look at the text at all.
2
(V−N)−1/N=V\big(V^{-N}\big)^{-1/N}=V. ∎ A fair die with VV faces. Any model worth training should beat this.

In one sentence: Perplexity is 2 raised to the average surprise in bits — the number of faces on the model's die — so 1 is perfect, VV is knowing nothing, 0.5 · 0.25 · 0.5 · 0.125 gives about 3.364, and it only compares models tested on the same text.

5

You shall know a word by the company it keeps

How can you learn what a word means without ever opening a dictionary?

Imagine this

You hear a word you do not know: "kadak". Then you hear it used: "a cup of kadak chai", "I like my chai kadak", "kadak and sweet, please". You still have no dictionary. But you already know it has something to do with strong tea.

You learned the word from its neighbours. The linguist J. R. Firth put it in one line in 1957: "You shall know a word by the company it keeps."

The counting of Act II only asked "what comes next?". Now we ask a wider question: "what is around?". There are two classic ways to write the company down in a table.

1 · Word × document. Rows are words, columns are documents, and each box counts how often the word appears in that document. A row answers "which documents talk about this word?". This term–document table is how search engines began: to answer the query "chai", look along the row for chai.

2 · Word × word. Rows are the words we want to understand (the targets), columns are neighbour words, and each box counts how often the neighbour appears within a few words of the target. How many words either side count as "near" is the window size. With a window of 2, here is the table from a small made-up corpus (the widget shows its sentences):

drinkhotplaymatch
chai5401
coffee4500
cricket0054
football0145

This is a co-occurrence matrix: "how often do these two words occur together". Read each row as a vector. Chai is (5,4,0,1)(5,4,0,1), coffee is (4,5,0,0)(4,5,0,0), cricket is (0,0,5,4)(0,0,5,4). These are our first real word vectors, and they are no longer one-hot: chai and coffee share neighbours, so their rows look alike.

How alike? Use the angle between the rows, from Unit 3:

cos⁡θ=a⋅b∥a∥ ∥b∥.\cos\theta=\frac{\mathbf a\cdot\mathbf b}{\lVert\mathbf a\rVert\,\lVert\mathbf b\rVert}.

For chai and coffee the dot product is 5⋅4+4⋅5+0+0=405\cdot4+4\cdot5+0+0=40, and the lengths are 42\sqrt{42} and 41\sqrt{41}. So

cos⁡(chai,coffee)=4042 41≈0.964.\cos(\text{chai},\text{coffee})=\frac{40}{\sqrt{42}\,\sqrt{41}}\approx0.964.

For chai and cricket the dot product is only 1⋅4=41\cdot4=4, so the cosine is 4/(4241)≈0.0964/(\sqrt{42}\sqrt{41})\approx0.096. Cricket and football give 40/(4142)≈0.96440/(\sqrt{41}\sqrt{42})\approx0.964 again. The tea words point almost the same way, the sport words point almost the same way, and the two groups are nearly at right angles.

Why the angle and not the length? A word used ten times as often has counts ten times as big — a longer arrow — but the same kind of company. The cosine ignores the length and keeps only the direction: which company a word keeps, not how often it talks.

Counting the companyTwo ways to write down company. Word × word: the corpus on the left builds the table on the right; change the window and it rebuilds. Word × document: four tiny documents, counted by document — and the question "who is most like chai?" answered both ways.

Try: With window 2 you get exactly the table above. Set the window to 1: chai loses its "drink" (it sits two words away in "drink hot chai") and chai–cricket drops to 0. Pick cricket and football, then chai and cricket, and compare the angles. Then open word × document: by neighbours chai's closest word is coffee (0.972); by documents it is kettle (0.8), and coffee drops to 0.

2
compare
Why does this work?

Because words that mean similar things are used in similar places. Chai and coffee both sit after "drink" and "hot"; cricket and football both sit near "play" and "match". Similar use gives similar rows, and similar rows point the same way. And the window size decides the kind of similarity. A small window (one or two words) finds words that can replace each other in a sentence — chai and coffee both fit "a cup of hot ___". A big window, like a whole document, finds words about the same topic — chai, kettle and cup live in the same documents even though "a cup of hot kettle" makes no sense.

Trap

"Similar" is not "means the same". Good and bad keep almost identical company ("a ___ day", "a very ___ idea"), so their rows are close — yet they are opposites. Company tells you a word's kind and topic; it cannot always tell you which way round the meaning goes.

The realization

word ↦ its row ofneighbour counts,similar=cos⁡θ near 1\begin{gathered}\text{word}\ \mapsto\ \text{its row of}\\ \text{neighbour counts},\\ \text{similar}=\cos\theta\ \text{near }1\end{gathered}

A word's row in a company table is a first, honest word vector. Words used in the same places get rows that point the same way. We did not tell the computer that chai and coffee are drinks — the counts told it. Small windows find stand-ins, big windows find topic-mates.

Pause & predict

From the table, what is the cosine between coffee (4,5,0,0)(4,5,0,0) and football (0,1,4,5)(0,1,4,5)?

Pause & predict

Suppose chai were twice as common, so its row became (10,8,0,2)(10,8,0,2). What happens to its cosine with coffee?

Pause & predict

You widen the window from two words to a whole paragraph. Which pair becomes more alike?

If you want the algebra · 1 proof, step by step
Prove it · the cosine ignores how often a word is used

Claim. For any numbers s,t>0s,t>0: cos⁡(sa, tb)=cos⁡(a,b)\cos(s\mathbf a,\,t\mathbf b)=\cos(\mathbf a,\mathbf b).

1
Scaling pulls out of the dot product and out of the lengths: (sa)⋅(tb)=st (a⋅b),∥sa∥ ∥tb∥=st ∥a∥ ∥b∥.\begin{aligned}(s\mathbf a)\cdot(t\mathbf b)&=st\,(\mathbf a\cdot\mathbf b),\\ \lVert s\mathbf a\rVert\,\lVert t\mathbf b\rVert&=st\,\lVert\mathbf a\rVert\,\lVert\mathbf b\rVert.\end{aligned} Lengths of positive multiples scale by the same factor.
2
The factor stst cancels in the ratio. ∎ So chai's row (10,8,0,2)(10,8,0,2) and (5,4,0,1)(5,4,0,1) have the same cosine with coffee: 80/(16841)=40/(4241)≈0.96480/(\sqrt{168}\sqrt{41})=40/(\sqrt{42}\sqrt{41})\approx0.964.

In one sentence: Count the company a word keeps — by document or by neighbours within a window — and each row becomes a word vector whose angle to another row says how alike their company is: 0.964 for chai and coffee, 0.096 for chai and cricket, stand-ins with small windows, topic-mates with big ones.

6

Not all company counts: TF-IDF and PMI

"The" sits next to chai more often than any other word. Does that make "the" the best clue to what chai means?

Imagine this

Two people are seen together at the market. If both of them go to the market every single day, meeting there means nothing — they would bump into each other anyway. But if both rarely leave home and yet keep turning up at the same stall, that means a lot.

A meeting only tells you something when it happens more often than chance would explain.

Raw counts reward words that are everywhere. "The", "is" and "a" sit next to every word and appear in every document, so they swamp both of our tables. We need to weigh each count by how surprising it is. There is one standard fix for each table.

For the term–document table: TF-IDF. Give each count a weight

weight=tf×log⁡10Ndf.\text{weight}=\text{tf}\times\log_{10}\frac{N}{\text{df}}.

Read it aloud: tf, the term frequency, is how often the word appears in this document. df, the document frequency, is how many of the NN documents contain the word at all. The log part, the idf, is large for rare words and exactly 0 for a word that is in every document, because log⁡1=0\log 1=0.

Take three documents. D1 has "the" 3 times, "chai" twice and "hot" once. D2 has "the" twice and "cricket" three times. D3 has "the", "chai" and "cricket" once each. Then

  • "the" is in all 3 documents: idf =log⁡10(3/3)=0=\log_{10}(3/3)=\mathbf0.
  • "chai" and "cricket" are in 2 of 3: idf =log⁡101.5≈0.176=\log_{10}1.5\approx\mathbf{0.176}.
  • "hot" is in 1 of 3: idf =log⁡103≈0.477=\log_{10}3\approx\mathbf{0.477}.

So in D1, chai weighs 2×0.176=0.3522\times0.176=0.352, hot weighs 0.4770.477, and "the" weighs 00 despite being the most frequent word. In D2 cricket weighs 3×0.176=0.5283\times0.176=0.528; in D3 chai and cricket weigh 0.176 each. A word that is in every document says nothing about any one of them.

For the word × word table: PMI. Ask how many times more often two words meet than two strangers would by chance. If chai and "hot" had nothing to do with each other, they would meet with probability P(chai) P(hot)P(\text{chai})\,P(\text{hot}) (independence, Unit 14). So compare the real meetings with that:

PMI⁡(w,c)=log⁡2P(w,c)P(w) P(c).\operatorname{PMI}(w,c)=\log_2\frac{P(w,c)}{P(w)\,P(c)}.

This is the pointwise mutual information. Worked example, with N=40N=40 counted pairs: chai meets hot 8 times, "the" 10 times and "match" 2 times; cricket meets hot 2 times, "the" 10 times and "match" 8 times. Add up the rows and columns first. Chai and cricket each take part in 20 of the 40 pairs; hot in 10, "the" in 20 and match in 10. So P(chai)=20/40=0.5P(\text{chai})=20/40=0.5, P(hot)=10/40=0.25P(\text{hot})=10/40=0.25, P(the)=20/40=0.5P(\text{the})=20/40=0.5, P(match)=10/40=0.25P(\text{match})=10/40=0.25, and P(chai,hot)=8/40=0.2P(\text{chai},\text{hot})=8/40=0.2:

PMI⁡(chai,hot)=log⁡20.20.5⋅0.25=log⁡21.6≈0.678,PMI⁡(chai,the)=log⁡20.250.5⋅0.5=0,PMI⁡(chai,match)=log⁡20.050.5⋅0.25≈−1.322.\begin{aligned}&\operatorname{PMI}(\text{chai},\text{hot})\\ &\quad=\log_2\frac{0.2}{0.5\cdot0.25}=\log_21.6\approx0.678,\\ &\operatorname{PMI}(\text{chai},\text{the})\\ &\quad=\log_2\frac{0.25}{0.5\cdot0.5}=0,\\ &\operatorname{PMI}(\text{chai},\text{match})\\ &\quad=\log_2\frac{0.05}{0.5\cdot0.25}\approx-1.322.\end{aligned}

Raw counts said "the" was chai's biggest neighbour (10 meetings). PMI says it tells us nothing: chai meets "the" exactly as often as chance predicts. Negative values mean "meet less often than chance", and they are noisy with small counts, so people usually keep only the positive part, PPMI⁡=max⁡(PMI⁡,0)\operatorname{PPMI}=\max(\operatorname{PMI},0).

From raw counts to surprisePMI: edit the counts, then walk the four steps — what chance alone would give, the ratio, its log, and the positive part. TF-IDF: the same idea for documents. In steps ① and ② the shade only shows how big a number is; from step ③ on, blue means "more than chance" and red "less than chance".

Try: Walk the steps ① to ⑤ and watch the "the" column fade to 0 while chai–hot stays at 0.678. Then raise chai–"the" from 10 to 14: PMI(chai, the) turns positive. Last, open TF-IDF: "the" is the commonest word in D1, yet its weight is 0.

Why does this work?

Chance alone would already put common words next to everything. Dividing by what chance would give — P(w)P(c)P(w)P(c) for PMI, the share of documents that contain the word for IDF — cancels the part of a count that is just popularity, and leaves the part that is about this pair. What survives is company that is actually informative.

Trap

PMI over-rewards rare pairs. In a corpus of a million pairs, two words that each appear once, and appear together, get log⁡2(106)≈19.9\log_2(10^6)\approx19.9 bits — the biggest number in the table, from a single sighting that may be a typo. That is why people ignore very rare words, or gently raise the counts of the neighbour words to a power below 1, such as 0.75 (the same trick returns in §12).

The realization

PMI⁡(w,c)=log⁡2P(w,c)P(w) P(c),tf-idf=tf⋅log⁡10Ndf\begin{gathered}\operatorname{PMI}(w,c)=\log_2\frac{P(w,c)}{P(w)\,P(c)},\\ \text{tf-idf}=\text{tf}\cdot\log_{10}\frac{N}{\text{df}}\end{gathered}

Not all company counts. Weigh each meeting by how much more often it happens than chance would allow: PMI for pairs of words, TF-IDF for words in documents. A neighbour that is everywhere, like "the", gets weight 0.

Pause & predict

A word appears in every one of 1 000 documents — 50 times in one of them. What is its TF-IDF weight in that document?

Pause & predict

With the same 40 pairs, cricket meets hot 2 times. What is PMI⁡(cricket,hot)\operatorname{PMI}(\text{cricket},\text{hot}), and what is its PPMI?

Pause & predict

Two rare words each appear once in a million counted pairs — and that one time, they appear together. What does PMI say about them?

If you want the algebra · 2 proofs, step by step
Prove it · PMI straight from the counts

Claim. With n(w,c)n(w,c) meetings out of NN counted pairs, row total n(w)n(w) and column total n(c)n(c): PMI⁡(w,c)=log⁡2n(w,c) Nn(w) n(c)\operatorname{PMI}(w,c)=\log_2\dfrac{n(w,c)\,N}{n(w)\,n(c)} — the count divided by what chance alone would give, n(w) n(c)/Nn(w)\,n(c)/N.

1
Turn counts into probabilities: P(w,c)=n(w,c)/NP(w,c)=n(w,c)/N, P(w)=n(w)/NP(w)=n(w)/N, P(c)=n(c)/NP(c)=n(c)/N. Every probability here is a share of the same NN pairs.
2
Divide, and two of the three NNs cancel: P(w,c)P(w)P(c)=n(w,c)/Nn(w) n(c)/N2=n(w,c)n(w) n(c)/N.\begin{aligned}&\frac{P(w,c)}{P(w)P(c)}\\ &=\frac{n(w,c)/N}{n(w)\,n(c)/N^2}\\ &=\frac{n(w,c)}{n(w)\,n(c)/N}.\end{aligned} The bottom, n(w) n(c)/Nn(w)\,n(c)/N, is the "if strangers" count of the widget's step ②.
3
Chai and hot: 8/(20⋅10/40)=8/5=1.68\big/(20\cdot10/40)=8/5=1.6, so PMI⁡=log⁡21.6≈0.678\operatorname{PMI}=\log_21.6\approx0.678. Chai and "the": 10/(20⋅20/40)=110\big/(20\cdot20/40)=1, so PMI⁡=0\operatorname{PMI}=0. ∎ Strangers score exactly 0: if ww and cc are independent, P(w,c)=P(w)P(c)P(w,c)=P(w)P(c), the ratio is 1 and its log is 0.
Prove it · a word in every document weighs nothing

Claim. If a word appears in all NN documents, its TF-IDF weight is 0 in every document, however often it appears.

1
Its document frequency is df=N\text{df}=N, so idf=log⁡10(N/N)=log⁡101=0\text{idf}=\log_{10}(N/N)=\log_{10}1=0. The log of 1 is 0 in any base.
2
The weight is tf×0=0\text{tf}\times0=0 for every tf. ∎ "the" in D1: 3×log⁡10(3/3)=03\times\log_{10}(3/3)=0. Meanwhile "hot", in just one of 3 documents, gets 1×log⁡103≈0.4771\times\log_{10}3\approx0.477.

In one sentence: Weigh company by surprise, not by size — PMI =log⁡2P(w,c)P(w)P(c)=\log_2\frac{P(w,c)}{P(w)P(c)} gives chai–hot 0.678 and chai–the exactly 0, and TF-IDF gives any word found in every document the weight 0 — but beware rare pairs, which PMI over-rewards.

7

Squeeze the table: the SVD finds friends of friends

In our text, chai and tea never share a single neighbour. Can the machine still discover that they are alike?

Imagine this

A school gives a long survey with 100 questions. When the teacher reads the answers, she notices that most of them can be summed up in two scores: "loves sport" and "loves music". Two numbers per student say almost everything the 100 answers say.

A company table is like that survey. It is huge, but most of what it says fits in a few numbers per word.

A real table has one row for every word and one column for every neighbour word: 50 000 × 50 000, mostly zeros. Rows that long are clumsy. We want short rows that keep the pattern and drop the noise.

The tool is the SVD from Unit 5. It writes any matrix as C=UΣVTC=U\Sigma V^{\mathsf T}: a turn, a stretch by the singular values σ1≥σ2≥…\sigma_1\ge\sigma_2\ge\dots, and another turn. Big singular values are the strong patterns; small ones are mostly noise. Keep only the top kk and you get the best rank-kk copy of the table (Unit 5's layer cake). Each word's new, short vector is its row of UkΣkU_k\Sigma_k.

For our 4 × 4 table of §5 the singular values are σ≈(9.528, 8.528, 1.143, 1.087)\sigma\approx(9.528,\ 8.528,\ 1.143,\ 1.087): two big, two small. Measure a table's "energy" as the sum of the squares of all its entries — here 42+41+41+42=16642+41+41+42=166, which also equals σ12+⋯+σ42\sigma_1^2+\dots+\sigma_4^2. The top two keep

σ12+σ22σ12+⋯+σ42≈163.5166≈98.5%\frac{\sigma_1^2+\sigma_2^2}{\sigma_1^2+\dots+\sigma_4^2}\approx\frac{163.5}{166}\approx98.5\%

of the energy, and rebuilding the table from just those two leaves an error of σ32+σ42≈1.578\sqrt{\sigma_3^2+\sigma_4^2}\approx1.578 — small next to entries of 4 and 5. Each word now gets two numbers:

chai≈(5.009, −4.032)coffee≈(4.530, −4.452)cricket≈(4.450, 4.540)football≈(5.037, 4.004)\begin{aligned}\text{chai}&\approx(5.009,\,-4.032)\\ \text{coffee}&\approx(4.530,\,-4.452)\\ \text{cricket}&\approx(4.450,\,4.540)\\ \text{football}&\approx(5.037,\,4.004)\end{aligned}

(The SVD may flip the sign of any direction, so another program may print some of these with the opposite sign; the angles do not change.) The first number is about 5 for every word: it says "this word is used a lot". The second is the interesting one: negative for tea, positive for sport. In two numbers, cos⁡(chai,coffee)≈0.995\cos(\text{chai},\text{coffee})\approx0.995 and cos⁡(chai,cricket)≈0.097\cos(\text{chai},\text{cricket})\approx0.097. The squeeze made the tea words even more alike — it threw away the noise that kept them apart.

Weigh first, then squeeze. On real text, run the SVD on the PPMI table of §6, not on raw counts. Otherwise the loud columns like "the" take over the first direction, and it only says "how common is this word".

Now the surprise: friends of friends. Here is a new table with seven neighbour words:

drinkhotcupkettleplaymatchbat
chai4400000
tea0044000
coffee3333000
cricket0000440
football0000044

Chai and tea never share a single neighbour, so their raw cosine is exactly 0. But coffee shares neighbours with both of them. The singular values are 68≈8.246\sqrt{68}\approx8.246, 48≈6.928\sqrt{48}\approx6.928, 32≈5.657\sqrt{32}\approx5.657, 44 and 00, so the energy kept is 41.5% at k=1k=1, 70.7% at k=2k=2 and 90.2% at k=3k=3.

Squeeze to k=2k=2. The words get the coordinates chai (4,0)(4,0), tea (4,0)(4,0), coffee (6,0)(6,0), cricket (0, 4.899)(0,\ 4.899), football (0, 4.899)(0,\ 4.899). Chai and tea now sit on the very same line: cos⁡(chai,tea)=1\cos(\text{chai},\text{tea})=\mathbf1. Coffee, a friend of both, made them friends. The rebuilt table even fills in the blanks: it gives chai a count of 2 next to cup and next to kettle, words it never met — because coffee meets them.

Keep one more direction, k=3k=3, and the new direction gives chai −4-4 and tea +4+4: it records exactly what makes them different. The cosine drops back to 0. Squeeze enough and hidden friendships appear; keep everything and you keep the differences too. Using the SVD this way on a word–document table is called latent semantic analysis (LSA) — "latent" because it finds similarities that no single count shows.

Sixteen words, squeezed into 1, 2 or 3 numbersA made-up table of 16 words × 12 neighbour words, squeezed by the SVD to kk numbers per word. Each word is drawn as its direction, so the angle between two dots is exactly what the cosine measures. Colours are only our labels — the SVD never sees them. Point at a dot to read its word.

Try: Start at k=1k=1 with raw counts: every word points the same way — the first direction only says "how common". Slide to k=2k=2, then 3: the groups open up, but only a little. Now switch to PPMI: three clean arms at right angles, one per topic. Read cos(chai, cricket) in the box: 0.525 with raw counts (both words share the loud "the" column), about 0 with PPMI.

drag the picture to orbit · point at a dot to read it

3
Friends of friendsThe chai · tea · coffee table, rebuilt from its top kk directions. Gold boxes are blanks the squeeze filled in. On the right, the three drink words drawn in the plane of direction 1 (drinks) and direction 3 (chai versus tea), where their angles are exact.

Try: At k=2k=2 chai and tea lie on one line — cosine 1 — and the rebuilt table gives chai a 2 for cup and for kettle, though it never met them. Slide to k=3k=3: direction 3 opens up, chai and tea swing apart to 90°, and the blanks empty again. k=4k=4 only separates cricket from football.

2
Why does this work?

The squeeze keeps only the few directions that explain the most counts. A direction is shared by groups of words and groups of neighbours, so it cannot fit chai's two neighbours and tea's two neighbours separately — it fits "the drink neighbours" as one block, because coffee connects the two halves. Words that only reach each other through a friend get pulled onto the same direction. The detail that tells them apart lives in a weaker direction, and a small kk throws it away.

Trap

A bigger kk is not always better. kk too small, and different topics are squashed together; kk too large, and you keep the noise and the small differences, so hidden friendships vanish again. For words people usually keep a few hundred directions out of tens of thousands. And the sign of each direction is arbitrary — never read meaning into a minus sign on its own.

The realization

C≈UkΣkVkT,word vectors=rows of UkΣk\begin{gathered}C\approx U_k\Sigma_kV_k^{\mathsf T},\\ \text{word vectors}=\text{rows of }U_k\Sigma_k\end{gathered}

The SVD finds the few strong directions hiding in a big table of counts. Keep those, drop the rest, and each word gets a short list of numbers; the energy kept, ∑i≤kσi2/∑iσi2\sum_{i\le k}\sigma_i^2/\sum_i\sigma_i^2, tells you how much of the table survived. Because each direction is shared by whole groups of words, the squeeze also finds friends of friends.

Pause & predict

A table has singular values 3, 2, 13,\ 2,\ 1. What share of the energy do you keep with k=1k=1?

Pause & predict

A table has singular values 5, 3, 0.4, 0.35,\ 3,\ 0.4,\ 0.3. You keep k=2k=2. How big is the rebuild error (Frobenius)?

Pause & predict

In the friends-of-friends table, chai and tea have cosine 1 at k=2k=2. What happens to their cosine at k=3k=3?

If you want the algebra · 3 proofs, step by step
Prove it · the energy of a table is the sum of σ²

Claim. For any matrix C=UΣVTC=U\Sigma V^{\mathsf T}, the sum of the squares of all entries equals σ12+σ22+⋯\sigma_1^2+\sigma_2^2+\cdots.

1
The sum of squares of all entries is tr⁡(CTC)\operatorname{tr}(C^{\mathsf T}C): the diagonal of CTCC^{\mathsf T}C holds the squared lengths of the columns. tr⁡\operatorname{tr} means "add the diagonal".
2
Substitute the SVD and use UTU=IU^{\mathsf T}U=I: CTC=VΣTΣVT.C^{\mathsf T}C=V\Sigma^{\mathsf T}\Sigma V^{\mathsf T}. A trace does not change when you turn the space (tr⁡(VMVT)=tr⁡(M)\operatorname{tr}(VMV^{\mathsf T})=\operatorname{tr}(M) for orthogonal VV), so the trace is tr⁡(ΣTΣ)=∑σi2\operatorname{tr}(\Sigma^{\mathsf T}\Sigma)=\sum\sigma_i^2. ∎ Our table: 166166 entry-by-entry, and 9.5282+8.5282+1.1432+1.0872≈1669.528^2+8.528^2+1.143^2+1.087^2\approx166.
Prove it · what is lost when you keep k directions

Claim. Keeping the top kk terms, Ck=∑i≤kσiuiviTC_k=\sum_{i\le k}\sigma_i\mathbf u_i\mathbf v_i^{\mathsf T}, leaves an error of size ∥C−Ck∥F=σk+12+σk+22+⋯\lVert C-C_k\rVert_F=\sqrt{\sigma_{k+1}^2+\sigma_{k+2}^2+\cdots}, and no other rank-kk matrix does better.

1
The SVD is a sum of layers: C=∑iσiuiviTC=\sum_i\sigma_i\mathbf u_i\mathbf v_i^{\mathsf T}. So the leftover is C−Ck=∑i>kσiuiviTC-C_k=\sum_{i>k}\sigma_i\mathbf u_i\mathbf v_i^{\mathsf T}, which is itself an SVD with singular values σk+1,σk+2,…\sigma_{k+1},\sigma_{k+2},\dots The layers are the ones of Unit 5's layer cake.
2
By the energy proof above, its squared size is ∑i>kσi2\sum_{i>k}\sigma_i^2. That no rank-kk matrix does better is the Eckart–Young theorem; its proof is in Unit 12.
3
For our table, k=2k=2: 1.1432+1.0872≈1.578\sqrt{1.143^2+1.087^2}\approx1.578. ∎ The energy kept is 1−error2/total=1−2.49/166≈98.5%1-\text{error}^2/\text{total}=1-2.49/166\approx98.5\%.
Prove it · coffee makes chai and tea friends

Claim. In the friends table, v1=12(1,1,1,1,0,0,0)\mathbf v_1=\tfrac12(1,1,1,1,0,0,0) is the top direction, with σ1=68\sigma_1=\sqrt{68}; chai and tea both get the coordinate 4 on it (coffee gets 6). The direction v3=12(−1,−1,1,1,0,0,0)\mathbf v_3=\tfrac12(-1,-1,1,1,0,0,0) has σ3=32\sigma_3=\sqrt{32} and gives chai −4-4, tea +4+4.

1
The directions of the SVD are the eigenvectors of CTCC^{\mathsf T}C (Unit 5). On the four drink columns, CTCC^{\mathsf T}C adds up chai's, tea's and coffee's contributions: (252599252599992525992525).\begin{pmatrix}25&25&9&9\\ 25&25&9&9\\ 9&9&25&25\\ 9&9&25&25\end{pmatrix}. Chai gives 4⋅4=164\cdot4=16 in the top-left block, tea 16 in the bottom-right block, coffee 3⋅3=93\cdot3=9 everywhere.
2
Multiply by (1,1,1,1)(1,1,1,1): every row gives 25+25+9+9=6825+25+9+9=68. Multiply by (−1,−1,1,1)(-1,-1,1,1): the first rows give −25−25+9+9=−32-25-25+9+9=-32, the last +32+32. So the eigenvalues are 68 and 32, and σ=68≈8.246\sigma=\sqrt{68}\approx8.246, 32≈5.657\sqrt{32}\approx5.657. The sport columns give eigenvalues 48 and 16, so 68\sqrt{68} is the biggest of all.
3
A word's coordinate is its row dotted with the direction. On v1\mathbf v_1: chai 12(4+4)=4\tfrac12(4+4)=4, tea 12(4+4)=4\tfrac12(4+4)=4, coffee 12(3+3+3+3)=6\tfrac12(3+3+3+3)=6. On v3\mathbf v_3: chai 12(−4−4)=−4\tfrac12(-4-4)=-4, tea 12(4+4)=4\tfrac12(4+4)=4, coffee 0. ∎ So at k=2k=2 chai and tea are both (4,0)(4,0): cosine 1. At k=3k=3 they are (4,0,−4)(4,0,-4) and (4,0,4)(4,0,4): dot product 16−16=016-16=0, cosine 0.

In one sentence: The SVD squeezes a company table to its top kk directions (98.5% of our 4 × 4 table at k=2k=2), and because each direction is shared by groups of words it finds friends of friends — chai and tea, who never meet, get cosine 1 at k=2k=2 through coffee, and 0 again when k=3k=3 keeps their difference.

8

From counting to predicting: the word2vec idea

Counting worked. So why did the people who built word2vec stop counting?

Imagine this

A new teacher joins a school and wants to know which children are friends. She could keep a register: every lunch, for a whole year, write down who sat next to whom. At the end she owns a giant table.

Or she could play a game. Each lunch, before the children sit down, she guesses who will sit next to whom, and she corrects herself whenever she is wrong. After a month she has no register at all — but she knows the friendships. The knowledge lives in her head.

Acts II and III kept the register. The company table of §5 has a row and a column for every word: with 50 000 words that is 2.5 billion boxes, almost all of them zero. New text means counting again, and squeezing such a table with the SVD (§7) is heavy work.

In 2013 Tomas Mikolov and his team at Google played the teacher's game instead. Their method is called word2vec, and its motto could be: don't write down the gossip — train a guesser, then read its mind.

Here is the game. Slide a window along the text, one word at a time. The word in the middle is the centre word. The words up to CC places on either side are its context. At every stop the machine plays one of two games:

  • Fill in the blank. Hide the centre word and guess it from the context. This game is called CBOW (§9).
  • Guess the neighbours. Show the centre word and guess each context word. This game is called skip-gram (§10).

Take we drink hot chai every morning with C=2C=2, and stop at "hot". Its context is we, drink, chai, every. CBOW makes one example from this stop: (we, drink, chai, every) → hot. Skip-gram makes four pairs: hot → we, hot → drink, hot → chai, hot → every.

Now count over the whole sentence. CBOW makes one example at each of the 6 stops: 6 examples. Skip-gram makes one pair per neighbour, and the words near the ends have fewer neighbours: 2+3+4+4+3+2=182+3+4+4+3+2=\mathbf{18} pairs. Keep that ratio in mind. It is the whole difference in cost between the two games (§11).

The sliding window: one sentence, two kinds of examplesA window of C words on each side slides along the sentence. At every stop, CBOW makes one fill-in-the-blank example (the neighbours guess the middle word); skip-gram makes one guess per neighbour (the middle word guesses each neighbour).

Try: Press ▶ slide on “we drink hot chai every morning” with window 2: CBOW makes 6 examples, skip-gram makes 18 pairs (2 + 3 + 4 + 4 + 3 + 2). The first and last stops hang over the edge of the sentence, so they have fewer neighbours. Flip between CBOW and skip-gram and watch the arrows turn round. Then try window 1 and window 4.

sentence
2
game
CBOW examples 0
skip-gram pairs 0

One small network plays both games. It is made of just two tables of numbers, and it works in four moves.

  1. Look up. Every word owns a row in the input table WinW_{\text{in}}, which has VV rows of dd numbers. The row of word ww is its input vector vw\mathbf v_w. Feeding a one-hot word into the table simply picks out its row (§14 shows why).
  2. Form one opinion, h\mathbf h. CBOW averages the rows of the context words. Skip-gram just takes the centre word's row. Either way h\mathbf h is a list of dd numbers.
  3. Score every word. Every word also owns a column in the output table WoutW_{\text{out}}, its output vector uw\mathbf u_w. Its score is the dot product uw⋅h\mathbf u_w\cdot\mathbf h — how well it lines up with the opinion (Unit 3).
  4. Turn scores into chances with a softmax over the whole vocabulary (Unit 14), and learn from the surprise at the true word.

Read the shapes along the way: V→d→VV\to d\to V. With V=50 000V=50\,000 words and d=300d=300, every word has to squeeze through a doorway only 300 numbers wide.

The network that plays both games, with the toy numbers of §9–§10 (V=5V=5 words, d=2d=2). Input vectors are blue rows; output vectors are green columns. Real models use V≈50 000V\approx50\,000 and d≈300d\approx300.
Why does this work?

Because the doorway is narrow. The network cannot keep a separate answer for each of 50 000 words — it has only dd numbers per word. So words that must make the same guesses get pushed into nearly the same rows. Chai and coffee are guessed from the same neighbours and guess the same neighbours, so the only way to play well is to give them almost the same vectors. It is the same squeeze as the SVD of §7 — done by a guessing game instead of a formula.

Trap

word2vec is not a deep network. There is no bend in the middle: h\mathbf h is just a looked-up row, or an average of rows. All the learning lives in the two tables. And only one of them is the prize: after training we throw the game away and keep the input table. Its rows are the word vectors.

The realization

one-hot⏟V → Win   h ⏟d → Wout  scores⏟V\underbrace{\text{one-hot}}_{V}\ \xrightarrow{\ W_{\text{in}}\ }\ \underbrace{\ \mathbf h\ }_{d}\ \xrightarrow{\ W_{\text{out}}\ }\ \underbrace{\text{scores}}_{V}

word2vec replaces counting with guessing. A window slides along the text. At each stop a tiny two-table network either fills in the centre word from its context (CBOW) or guesses the context from the centre word (skip-gram). The guessing is only a test. What we keep is the input table, whose rows were forced to put words with the same company close together.

Pause & predict

A sentence has 5 words and the window is C=1C=1. How many examples does CBOW make, and how many pairs does skip-gram make?

Pause & predict

Training is over. Which part of the word2vec network do we keep as the word vectors?

If you want the algebra · 1 proof, step by step
Prove it · how many pairs skip-gram makes from one sentence

Claim. A sentence of nn words (with n≥C+1n\ge C+1) and a window of CC words on each side give CBOW nn examples and skip-gram 2Cn−C(C+1)2Cn-C(C+1) pairs.

1
Number the positions 0,1,…,n−10,1,\dots,n-1. Position ii has min⁡(i,C)\min(i,C) neighbours on its left and min⁡(n−1−i,C)\min(n-1-i,C) on its right. CBOW makes one example per position: nn. Near the ends the window hangs over the edge, so fewer neighbours fit.
2
Add up the left neighbours. The first C+1C+1 positions give 0+1+⋯+C0+1+\dots+C; every later position gives CC: 12C(C+1)+C (n−1−C)=Cn−12C(C+1).\begin{aligned}&\tfrac12C(C+1)\\ &\quad+C\,(n-1-C)\\ &=Cn-\tfrac12C(C+1).\end{aligned} The right neighbours add up to the same total — read the sentence backwards.
3
Left plus right: 2Cn−C(C+1)2Cn-C(C+1). ∎ Check: n=6n=6, C=2C=2 gives 24−6=1824-6=18. For a long text the ratio to CBOW's nn examples tends to 2C2C.

In one sentence: word2vec slides a window along the text and trains a tiny two-table network to guess each centre word from its neighbours (CBOW) or the neighbours from the centre word (skip-gram), then keeps the input table as the word vectors — don't write down the gossip, train a guesser and read its mind.

9

CBOW: the committee fills in the blank

How could a game of fill-in-the-blank teach a computer that chai is like coffee?

Imagine this

The teacher writes on the board: "Every morning my grandfather drinks a hot cup of ____." Nobody asks what the missing word is. "Chai," says the whole class.

You did not look anything up. The words around the blank — drinks, hot, cup — each pointed somewhere, and together they pointed at one word. A committee of neighbours voted on the blank.

That game — fill in the blank from the words around it — is the first way word2vec learns. It is called CBOW, the continuous bag of words.

Let us play one round by hand. We use a toy model with a vocabulary of five words and vectors of just d=2d=2 numbers, so that every step fits on paper. We chose the starting numbers by hand to keep the arithmetic clean; a real model starts from small random numbers.

wordinput vector v\mathbf voutput vector u\mathbf u
we(0, 1)(0, 0)
drink(1, 0)(1, 0)
chai(1, 1)(1, 1)
daily(0, 1)(0, 1)
cricket(−1, 0)(−1, −1)

Take the tiny sentence we drink chai daily, use a window of one word on each side, and hide the middle word, chai. The committee is drink and daily. The machine plays in four moves.

  1. Look up the neighbours. Their input vectors are drink = (1, 0) and daily = (0, 1).
  2. Average them. h=((1,0)+(0,1))/2=(0.5, 0.5)\mathbf h=\big((1,0)+(0,1)\big)/2=(0.5,\ 0.5). This single point is the committee's combined opinion.
  3. Score every word. Dot each output vector with h\mathbf h: we 0, drink 0.5, chai 1, daily 0.5, cricket −1.
  4. Turn scores into a guess. The softmax gives 0.135, 0.223, 0.368, 0.223, 0.050. The true word is chai, so the surprise is −ln⁡0.368≈1.00-\ln0.368\approx1.00.

Written as formulas, the four moves are:

h=12(vdrink+vdaily),sw=uw⋅h,p=softmax⁡(s),L=−ln⁡pchai.\begin{aligned}\mathbf h&=\tfrac12\big(\mathbf v_{\text{drink}}+\mathbf v_{\text{daily}}\big),\\ s_w&=\mathbf u_w\cdot\mathbf h,\\ \mathbf p&=\operatorname{softmax}(\mathbf s),\\ L&=-\ln p_{\text{chai}}.\end{aligned}

Read them aloud. The first line asks the committee for its average opinion. The second gives every word in the vocabulary a score: how well its answer-arrow lines up with that opinion. The third turns the scores into chances that add up to 1. The fourth measures how surprised the model was by the truth.

And now the name makes sense. Bag: averaging throws away the order of the neighbours — "drink … daily" and "daily … drink" give the same h\mathbf h, like words tipped into a bag. Continuous: the vectors are dense lists of real numbers, not counts.

How it learns. Unit 15 showed that the blame arriving at the scores of a softmax is simply prediction − truth:

e=p−y=(0.135, 0.223, −0.632,0.223, 0.050).\begin{aligned}\mathbf e=\mathbf p-\mathbf y=(&0.135,\ 0.223,\ -0.632,\\ &0.223,\ 0.050).\end{aligned}

Only chai's entry is negative, and negative blame means "raise me". One step (with step size η=1\eta=1) now does three things:

  • The answers move. Every output vector moves by −η ew h-\eta\,e_w\,\mathbf h. Chai's is pulled toward h\mathbf h: (1,1)+0.632 (0.5,0.5)=(1.316, 1.316)(1,1)+0.632\,(0.5,0.5)=(1.316,\ 1.316). Every other word's is pushed away from h\mathbf h, each in proportion to the probability it wrongly took.
  • The blame reaches the committee. The blame on h\mathbf h is ∑wew uw=(−0.458, −0.458)\sum_w e_w\,\mathbf u_w=(-0.458,\ -0.458). It says: move the opinion toward chai's answer-arrow.
  • The blame is shared equally. h\mathbf h was an average of two neighbours, so each member moves by half: −η⋅12(−0.458, −0.458)=(0.229, 0.229).-\eta\cdot\tfrac12(-0.458,\ -0.458)=(0.229,\ 0.229). Drink becomes (1.229, 0.229)(1.229,\ 0.229) and daily becomes (0.229, 1.229)(0.229,\ 1.229).

Play the same blank again. The model now gives chai 0.594 instead of 0.368, and the surprise drops from 1.00 to 0.52.

The committee machine: CBOW, one move at a timeThe neighbours’ input vectors (blue) are averaged into h (gold). Every word’s output vector (green) is scored against h, softmax turns the scores into a guess, and the error p − y decides who is pulled and who is pushed. Toy vectors set by hand, V = 5, d = 2.

Try: Press ▶ next move seven times: the guess for chai is 0.3682 and the loss 0.9993; after one update with η = 1 they become 0.5942 and 0.5205. Watch move ⑥: both neighbours move by the same little arrow, half of the blame each. Press ↻ another round to keep training: one blank has one right answer, so the loss heads toward 0. Then switch on window 2: four neighbours share the blame, so each gets a quarter.

1
    1the committee · input vectors
    2score every word · output vectors
    3the guess and the error
    input vector v (a row of the input table)h, the committee’s averageoutput vector u (a row of the output table)probabilityerror / blame
    Why does this work?

    Every time chai is the blank, its answer-arrow is pulled toward the average of the neighbours it had — and those neighbours are pulled toward chai's answer-arrow. Coffee is the blank in the same kinds of sentences (drink, hot, cup, morning), so its arrows receive the same pulls. Two words pulled toward the same places end up in the same place. Nobody told the machine that chai and coffee are drinks. The blanks did.

    Trap

    The vectors we keep are not the answers to the blanks. Each word has two vectors: an input vector v\mathbf v, used when it sits on the committee, and an output vector u\mathbf u, used when it is the answer. After training we throw the game away and keep the input table — the committee members' vectors. The game was only the test that forced that table to be good.

    The realization

    h=12C∑c ∈ contextvc,vc←vc−η2C∑w(pw−yw) uw\begin{aligned}\mathbf h&=\frac1{2C}\sum_{c\,\in\,\text{context}}\mathbf v_c,\\ \mathbf v_c&\leftarrow\mathbf v_c-\frac{\eta}{2C}\sum_w\big(p_w-y_w\big)\,\mathbf u_w\end{aligned}

    CBOW averages the context vectors, scores every word against that average, and nudges the vectors until the true centre word wins. With CC words on each side the committee has 2C2C members, and each member receives a 12C\tfrac1{2C} share of the blame.

    Pause & predict

    In the toy round, swap the two neighbours so the sentence reads we daily chai drink. What happens to the model's chance for chai?

    Pause & predict

    The window grows from one word on each side to two, so the committee has four members. What share of the blame on h\mathbf h does each member now receive?

    If you want the algebra · 1 proof, step by step
    Prove it · why the committee shares the blame equally

    Claim. With h=12C∑cvc\mathbf h=\frac1{2C}\sum_c\mathbf v_c, scores sw=uw⋅hs_w=\mathbf u_w\cdot\mathbf h and L=−ln⁡softmax⁡(s)oL=-\ln\operatorname{softmax}(\mathbf s)_o, the gradients are ∂L/∂uw=ew h\partial L/\partial\mathbf u_w=e_w\,\mathbf h and ∂L/∂vc=12C∑wew uw\partial L/\partial\mathbf v_c=\frac1{2C}\sum_w e_w\,\mathbf u_w for every context word cc, where e=p−y\mathbf e=\mathbf p-\mathbf y.

    1
    A softmax followed by cross-entropy sends back prediction − truth to the scores: ∂L/∂sw=pw−yw=ew\partial L/\partial s_w=p_w-y_w=e_w. Proved in Unit 15.
    2
    Each score is a dot product, so its slope is h\mathbf h with respect to uw\mathbf u_w, and uw\mathbf u_w with respect to h\mathbf h. Chain them: ∂L∂uw=ew h,∂L∂h=∑wew uw.\begin{aligned}\frac{\partial L}{\partial\mathbf u_w}&=e_w\,\mathbf h,\\ \frac{\partial L}{\partial\mathbf h}&=\sum_w e_w\,\mathbf u_w.\end{aligned} Local slope times incoming blame — Rule B of Unit 15.
    3
    Changing one vc\mathbf v_c moves h\mathbf h by only 12C\frac1{2C} of that change, so ∂L/∂vc=12C ∂L/∂h\partial L/\partial\mathbf v_c=\frac1{2C}\,\partial L/\partial\mathbf h — the same for every member. ∎ Toy round: ∂L/∂h=(−0.458,−0.458)\partial L/\partial\mathbf h=(-0.458,-0.458) and 2C=22C=2, so a step with η=1\eta=1 moves drink and daily by (0.229, 0.229)(0.229,\ 0.229) each.

    A note on the real program. The lab in §11 follows this exact rule: with nn words on the committee, each one gets 1n\tfrac1n of the blame on h\mathbf h, because h\mathbf h is their average. The original word2vec program (the C code released with the 2013 papers) takes a shortcut. It also averages the committee to make h\mathbf h, but then it hands every member the full blame on h\mathbf h, not a share. That is like giving the input vectors a step nn times bigger. It still learns well; it is simply not the exact slope of the average.

    In one sentence: CBOW averages the neighbours' vectors, scores every word against that average, and nudges the vectors until the true middle word wins — a committee of neighbours filling in the blank.

    10

    Skip-gram: one word guesses its neighbours

    What if we turn the game around, and ask one word to guess the company it keeps?

    Imagine this

    Show a friend one word cut out of yesterday's newspaper: wicket. Ask her which words were probably printed around it. "Bowler," she says. "Over. Six. Bat."

    One word, many guesses. And to make those guesses she had to know what a wicket is.

    That is the second game, skip-gram: the centre word throws a guess at each of its neighbours. (The name: a bigram of §2 is two words side by side; a skip-gram is a pair that may skip over the words in between. The centre word is paired with every word in its window.) We use the same toy model and the same sentence, we drink chai daily, with a window of one. This time chai is shown, and it must guess drink and daily.

    1. Look up the centre word. No committee, no averaging: h=vchai=(1, 1)\mathbf h=\mathbf v_{\text{chai}}=(1,\ 1).
    2. Score every word. we 0, drink 1, chai 2, daily 1, cricket −2.
    3. Make one list of chances. The softmax gives 0.072, 0.195, 0.529, 0.195, 0.010. The same list is used for every neighbour slot — the slot on the left and the slot on the right.
    4. Add up the surprises. The true neighbours, drink and daily, got 0.195 each: L=−ln⁡0.195−ln⁡0.195≈3.27L=-\ln0.195-\ln0.195\approx3.27.

    h=vchai,pw=softmax⁡(u⋅h)w,L=−ln⁡pdrink−ln⁡pdaily.\begin{aligned}\mathbf h&=\mathbf v_{\text{chai}},\\ p_w&=\operatorname{softmax}(\mathbf u\cdot\mathbf h)_w,\\ L&=-\ln p_{\text{drink}}-\ln p_{\text{daily}}.\end{aligned}

    Read it aloud: the centre word's own vector is the opinion; one list of chances covers the whole vocabulary; each true neighbour adds its own surprise.

    Now look at the model's favourite guess: chai itself, with 0.529. Chai's input vector and output vector are both (1, 1), so the word points straight at its own answer-arrow. But a word is almost never its own neighbour. Watch one step fix that.

    How it learns. Each neighbour slot sends back prediction − truth, and because both slots used the same list of chances, their errors simply add up:

    E=2 p−ydrink−ydaily=(0.143, −0.611, 1.059,−0.611, 0.019).\begin{aligned}\mathbf E&=2\,\mathbf p-\mathbf y_{\text{drink}}-\mathbf y_{\text{daily}}\\ &=(0.143,\ -0.611,\ 1.059,\\ &\qquad -0.611,\ 0.019).\end{aligned}

    • The answers move. Drink's and daily's output vectors are pulled toward h\mathbf h: they become (1.611, 0.611)(1.611,\ 0.611) and (0.611, 1.611)(0.611,\ 1.611). Chai's own output vector took 0.529 in both slots, so it is pushed hard away: (1,1)−1.059 (1,1)=(−0.059, −0.059)(1,1)-1.059\,(1,1)=(-0.059,\ -0.059).
    • The centre word takes all the blame. The blame on h\mathbf h is ∑wEw uw=(0.429, 0.429)\sum_w E_w\,\mathbf u_w=(0.429,\ 0.429). There is no committee to share it with, so vchai\mathbf v_{\text{chai}} moves by all of it: (1,1)−(0.429, 0.429)=(0.571, 0.571)(1,1)-(0.429,\ 0.429)=(0.571,\ 0.571). Chai stops pointing at itself.

    After this one step the chances are 0.092, 0.386, 0.102, 0.386, 0.034. Drink and daily are now the favourites, and the loss has fallen from 3.27 to 1.90.

    One word, many guesses: skip-gram, one move at a timeThe middle word’s own input vector is h — no averaging. One softmax guess is made and used for every neighbour slot; the errors of all the slots are added up, and the middle word takes the whole sum. Same toy vectors as the committee machine; the lab below plays a cheaper version, with negative sampling in place of this full softmax.

    Try: Press ▶ next move seven times: each neighbour slot gets probability 0.1947 and the loss is 3.2725; after one update with η = 1 each slot gets 0.3862 and the loss is 1.9026. At move ⑥ watch chai’s own output vector swing through the origin while its input vector shrinks to (0.5714, 0.5714): chai stops pointing at itself. Then press ↻ another round again and again: each slot creeps toward 0.5 and the loss toward 2 ln 2 ≈ 1.386, never lower — one list of chances must be shared by both neighbours.

    1
      1the middle word · its input vector
      2score every word · output vectors
      3one guess, used for every slot
      input vector v · here h = v(chai)output vector uprobabilityerror / blame
      Why does this work?

      One list must cover all the company. A single softmax has to spread its chances over all of a word's usual neighbours. The best this model could ever do for chai is 0.5 on drink and 0.5 on daily — a loss of 2ln⁡2≈1.3862\ln2\approx1.386, never 0. So skip-gram literally learns a word's company as a list of chances. Two words that keep the same company must produce the same list, and the only way to do that is to have nearly the same input vector.

      The centre word gets every update in full. It receives the sum of all its neighbours' errors. So even a word that appears only a few times gets strong, undiluted updates each time it does appear.

      Trap

      Skip-gram does not make a different guess for each position. The neighbour on the left and the neighbour two places to the right are guessed from the same list of chances. The window says which words count as company; it does not say where they sit.

      The realization

      L=−∑c ∈ contextln⁡pc,vcentre←vcentre−η∑wEw uw\begin{aligned}L&=-\sum_{c\,\in\,\text{context}}\ln p_c,\\ \mathbf v_{\text{centre}}&\leftarrow\mathbf v_{\text{centre}}-\eta\sum_w E_w\,\mathbf u_w\end{aligned}

      Skip-gram uses the centre word's own vector as the opinion, makes one softmax over the vocabulary, and checks it against every neighbour. The errors of all the slots add up, and the centre word receives the whole sum. (The lab in §11 plays a cheaper version of this game, with negative sampling in place of the full softmax — see §12.)

      Pause & predict

      In the skip-gram round, chai has two neighbours, drink and daily. How many softmax lists does the model work out for this one position?

      Pause & predict

      Why does a rare word usually end up with a better vector from skip-gram than from CBOW?

      Pause & predict

      In the whole text, chai's only neighbours are drink and daily, equally often. What is the lowest loss skip-gram can ever reach at this position?

      If you want the algebra · 2 proofs, step by step
      Prove it · skip-gram adds up the errors of all its neighbours

      Claim. For L=−∑cln⁡pcL=-\sum_{c}\ln p_c, with one list p=softmax⁡(s)\mathbf p=\operatorname{softmax}(\mathbf s) and sw=uw⋅hs_w=\mathbf u_w\cdot\mathbf h, the blame on the scores is E=∑c(p−yc)\mathbf E=\sum_c(\mathbf p-\mathbf y_c), and the blame on the centre word is ∑wEw uw\sum_w E_w\,\mathbf u_w.

      1
      Each term −ln⁡pc-\ln p_c is a softmax with cross-entropy, so it sends back p−yc\mathbf p-\mathbf y_c. The terms are added, so their blames add: E=∑c(p−yc).\mathbf E=\sum_c\big(\mathbf p-\mathbf y_c\big). With two neighbours: E=2p−ydrink−ydaily\mathbf E=2\mathbf p-\mathbf y_{\text{drink}}-\mathbf y_{\text{daily}}.
      2
      As in CBOW, the blame on h\mathbf h is ∑wEw uw\sum_w E_w\,\mathbf u_w. But now h\mathbf h is vcentre\mathbf v_{\text{centre}}, so the centre word receives the whole of it — nothing is divided. ∎ Toy: E=(0.143,−0.611,1.059,−0.611,0.019)\mathbf E=(0.143,-0.611,1.059,-0.611,0.019) gives (0.429, 0.429)(0.429,\ 0.429), and vchai\mathbf v_{\text{chai}} becomes (0.571, 0.571)(0.571,\ 0.571).
      Prove it · with two different neighbours the loss never reaches zero

      Claim. If a centre word's neighbours are two different words aa and bb, then L=−ln⁡pa−ln⁡pb≥2ln⁡2≈1.386L=-\ln p_a-\ln p_b\ge2\ln2\approx1.386, with equality only when pa=pb=12p_a=p_b=\tfrac12.

      1
      The chances of one softmax add up to 1, so pa+pb≤1p_a+p_b\le1. Both neighbours are read from the same list.
      2
      Two positive numbers with a fixed sum have the largest product when they are equal: pa pb≤(pa+pb2)2≤14.p_a\,p_b\le\Big(\frac{p_a+p_b}{2}\Big)^2\le\frac14. Because (x+y2)2−xy=(x−y2)2≥0\big(\tfrac{x+y}2\big)^2-xy=\big(\tfrac{x-y}2\big)^2\ge0.
      3
      So L=−ln⁡(pa pb)≥−ln⁡14=2ln⁡2L=-\ln(p_a\,p_b)\ge-\ln\tfrac14=2\ln2. ∎ A word with several different neighbours can never be sure of any one of them — which is exactly why its list of chances describes its company.

      In one sentence: Skip-gram looks up the centre word's vector, makes one softmax over the whole vocabulary and checks it against every neighbour — so it learns a word's company as a list of chances, and the centre word gets the full sum of its neighbours' blame.

      11

      CBOW or skip-gram? Race them

      Two games, one goal. Which one should you play?

      Imagine this

      A coaching class and home tuition. In the coaching class, the teacher asks one question and takes one answer from a room of forty. It is fast, but the quiet student in the back row barely changes the answer. At home tuition, the teacher sits with one student and asks question after question. It is slower and costs more — but the weak student gets full attention.

      CBOW is the coaching class. Skip-gram is home tuition. And the rare words are the quiet students.

      Both games read the same text through the same window, and both train the same two tables. Put them side by side:

      CBOW · fill in the blankskip-gram · guess the neighbours
      what goes in → what comes outthe context (up to 2C2C words) → the centre wordthe centre word → each context word
      guesses at each stop1up to 2C2C
      what is averagedthe 2C2C context vectorsnothing
      a word's share of the blame12C\tfrac1{2C} of the committee'sthe full sum of its neighbours'
      speedfaster — about 2C2C times fewer guessesslower
      frequent wordsslightly better, smoothergood
      rare words, small collections of textweakerbetter

      The rule of thumb comes from the people who built word2vec (Mikolov and colleagues, 2013): CBOW is several times faster and a little better for frequent words; skip-gram works well with small amounts of text and represents even rare words well. In practice the most popular choice is skip-gram with negative sampling (§12), a window of about 5 words and 100–300 numbers per word.

      Why do rare words do better in skip-gram? Follow the blame. In CBOW a rare word is one voice in a committee of 2C2C, so every update it receives is divided by the size of the committee — and the committee's answer is mostly shaped by the common words around it. In skip-gram the rare word is the centre of up to 2C2C guesses, and it receives every one of those updates in full.

      Below, both games train side by side: the same sentences, in the same order, from the same random start. Watch three things. The cost counters: at each stop skip-gram makes up to 2C2C guesses where CBOW makes one. The maps: both sort the words into topics they were never told about. And the nearest neighbours of a frequent word and of a rare word, in each model.

      CBOW vs skip-gram, raced on the same textBoth models read the same 102 short sentences in the same order, from the same random start, and learn by negative sampling. Each word gets 8 numbers; each map is a flat shadow (PCA) of them. The colours are our topic labels — the models never see them.

      Try: Press ▶ race. Within about 10 passes skip-gram’s map sorts itself into four colour groups; CBOW’s groups form more slowly — but CBOW does about 3 times less work (with window 2, skip-gram makes 2.95 guesses for every CBOW guess). At the end, compare the rare word kadak (seen 3 times): its “fits drinks” score is far higher for skip-gram, while for the everyday word chai the two models are close. Switch on slow motion to watch the guesses each model makes from one sentence.

      speed
      2
      5
      0.1
      CBOWthe committee fills each blank
      skip-grameach word guesses its neighbours

      fits drinks +0.57 = the word’s average cosine to the other drinks minus its average cosine to the words of the other topics. Higher means the word sits more firmly among the drinks. The topic score is the same idea for all the topic words at once.

      rare word to follow
      How tight are the topic groups? mean cosine inside a topic − mean cosine across topics
      Work done dot products computed so far
      Loss average surprise per guess, this pass
      Why does this work?

      Both games are fed by the same thing: which words share a window. Words that keep the same company receive the same pulls in either game, so both tables end up putting them together. The games differ only in how the pulls are packaged — one averaged guess per window, or one guess per neighbour — and that packaging decides the cost and how much attention each word gets.

      Trap

      Faster is not worse, and slower is not better. On a large collection of text both games reach vectors of similar quality; the choice is about time and about rare words. And a toy lab with about a hundred short sentences is noisy: change the random start before you judge a winner.

      The realization

      CBOW: 1 guess per stopskip-gram: up to 2Cguesses per stop\begin{gathered}\text{CBOW: 1 guess per stop}\\ \text{skip-gram: up to }2C\\ \text{guesses per stop}\end{gathered}

      CBOW buys speed by averaging the committee into one guess. Skip-gram pays about 2C2C times more to give every word — and especially every rare word — its own full update.

      Pause & predict

      You widen the window from C=2C=2 to C=4C=4. In the middle of a long sentence, how many guesses does each game now make at one stop?

      Pause & predict

      You have a small collection of old letters, full of rare village names, and plenty of computer time. Which game is the better bet?

      In one sentence: CBOW is the coaching class — one averaged guess per window, fast and smooth — while skip-gram is home tuition — up to 2C2C guesses per window, slower, but every word, especially every rare one, gets its full share of attention.

      12

      Making it cheap: negative sampling, hierarchical softmax, subsampling

      Every guess in §9 and §10 scored every word of the vocabulary — in a real model, all 50 000 of them. How could training on billions of words ever finish?

      Imagine this

      A teacher wants to check whether you know who chai's friends are. She could ask: "Out of all 50 000 students in this city, rank how likely each one is to be chai's friend." That takes all day.

      Or she could ask five quick yes-or-no questions: "Is hot a friend? Is football? Is kettle?…" Or she could play twenty questions: "Is the friend a drink word? Yes. A hot one? Yes…" — and find the answer in a handful of steps. Three ways to test the same knowledge. The last two are fast.

      The cost of the full softmax. To turn scores into chances, the softmax divides by a sum over the whole vocabulary:

      po=euo⋅h∑w=1Veuw⋅h.p_o=\frac{e^{\mathbf u_o\cdot\mathbf h}}{\sum_{w=1}^{V}e^{\mathbf u_w\cdot\mathbf h}}.

      That bottom line needs one dot product and one e(⋅)e^{(\cdot)} for every word — 50 000 of them for a single guess. Worse, every word takes a little probability, so every output vector receives a little blame and must be updated. word2vec makes billions of guesses. Something has to give.

      Way 1 · Negative sampling — a few yes/no questions. Replace "which one, out of everybody?" by "is this one real, or random?". For each real (centre, neighbour) pair, also pick kk random words — the negatives — and train the model to say "real" to the true neighbour and "random" to each negative. The score of a pair is a sigmoid of its dot product (Unit 14): P(real)=σ(u⋅v)P(\text{real})=\sigma(\mathbf u\cdot\mathbf v).

      A worked round, with lists of two numbers. Centre word chai: vchai=(1,0)\mathbf v_{\text{chai}}=(1,0). Real neighbour hot: uhot=(0.5,0.5)\mathbf u_{\text{hot}}=(0.5,0.5). One random negative, football: ufootball=(−0.5,1)\mathbf u_{\text{football}}=(-0.5,1).

      • Real pair: uhot⋅vchai=0.5\mathbf u_{\text{hot}}\cdot\mathbf v_{\text{chai}}=0.5, so σ(0.5)≈0.622\sigma(0.5)\approx0.622: the model is 62% sure hot is real.
      • Negative pair: ufootball⋅vchai=−0.5\mathbf u_{\text{football}}\cdot\mathbf v_{\text{chai}}=-0.5, so the chance it says "random" is σ(0.5)≈0.622\sigma(0.5)\approx0.622.
      • The loss is the surprise of both right answers (in nats, as in Unit 14): −ln⁡0.622−ln⁡0.622≈0.948-\ln0.622-\ln0.622\approx0.948.

      One step downhill (Unit 9) with η=1\eta=1. Each answer is "wrong by" 1−0.622≈0.3781-0.622\approx0.378, and the updates are the same pull-and-push we met in CBOW, now for only three vectors:

      • Pull the real neighbour toward chai: uhot←uhot+0.378 vchai=(0.878, 0.5)\mathbf u_{\text{hot}}\leftarrow\mathbf u_{\text{hot}}+0.378\,\mathbf v_{\text{chai}}=(0.878,\ 0.5).
      • Push the random word away: ufootball←ufootball−0.378 vchai=(−0.878, 1)\mathbf u_{\text{football}}\leftarrow\mathbf u_{\text{football}}-0.378\,\mathbf v_{\text{chai}}=(-0.878,\ 1).
      • Turn chai toward hot and away from football: vchai←vchai+0.378 (uhot−ufootball)=(1.378, −0.189)\mathbf v_{\text{chai}}\leftarrow\mathbf v_{\text{chai}}+0.378\,(\mathbf u_{\text{hot}}-\mathbf u_{\text{football}})=(1.378,\ -0.189).

      After this one step the real pair scores σ(1.114)≈0.753\sigma(1.114)\approx0.753, the negative gets "random" with σ(1.398)≈0.802\sigma(1.398)\approx0.802, and the loss has dropped from 0.948 to about 0.505. The cost: k+1k+1 dot products instead of VV. With V=50 000V=50\,000 and k=5k=5, that is 50 000/6≈8 33350\,000/6\approx8\,333 times less work.

      Which random words? If negatives were picked in proportion to how often words appear, "the" and "is" would be picked all the time and teach little. word2vec picks a word with probability proportional to its count raised to the power 34\tfrac34. That gently lifts rare words: a word seen 100 times and one seen once would share the picks 99% to 1%; after the 34\tfrac34 power it is 1000.75≈31.6100^{0.75}\approx31.6 against 1, about 96.9% to 3.1%.

      One round of the yes/no game, as arrowsChai's centre-word arrow in blue, the real neighbour "hot" in green, the random word "football" in orange. Each step pulls the real pair together and pushes the random pair apart.

      Try: Press one step once and check the numbers above: loss 0.948 → 0.505. Keep stepping: hot swings round toward chai, football swings round to the other side, and the loss slides toward 0. Try η=0.5\eta=0.5 and count how many more steps it takes to get the loss below 0.1 (4 steps at η=1\eta=1, 8 at η=0.5\eta=0.5).

      1

      Way 2 · Hierarchical softmax — twenty questions down a tree. Put all the words at the leaves of a binary tree. To give a word its chance, walk from the root to its leaf; at every fork, a small sigmoid decides "left or right?", and the word's chance is the product of the decisions along its path. Each fork nn has its own vector θn\boldsymbol\theta_n, and the chance of turning left is σ(θn⋅h)\sigma(\boldsymbol\theta_n\cdot\mathbf h).

      A four-leaf tree, with h=(1,1)\mathbf h=(1,1). The root asks "drink or sport?" with θ1=(0.5,0.5)\boldsymbol\theta_1=(0.5,0.5); the drink fork asks "chai or coffee?" with θ2=(−0.5,0)\boldsymbol\theta_2=(-0.5,0); the sport fork asks "cricket or football?" with θ3=(1,−2)\boldsymbol\theta_3=(1,-2). Then P(drink)=σ(1)=0.7311P(\text{drink})=\sigma(1)=0.7311, and

      P(chai)=0.7311 σ(−0.5)=0.2760,P(coffee)=0.7311 σ(0.5)=0.4551,P(cricket)=0.2689 σ(−1)=0.0723,P(football)=0.2689 σ(1)=0.1966.\begin{aligned}P(\text{chai})&=0.7311\,\sigma(-0.5)=0.2760,\\ P(\text{coffee})&=0.7311\,\sigma(0.5)=0.4551,\\ P(\text{cricket})&=0.2689\,\sigma(-1)=0.0723,\\ P(\text{football})&=0.2689\,\sigma(1)=0.1966.\end{aligned}

      These four add up to exactly 1 — and nobody ever added up all the words. Each fork splits its share into two parts that add up to what came in, because σ(z)+σ(−z)=1\sigma(z)+\sigma(-z)=1. With V=50 000V=50\,000 words, a balanced tree needs only ⌈log⁡250 000⌉=16\lceil\log_250\,000\rceil=\mathbf{16} decisions per guess instead of 50 000 scores. word2vec even builds the tree so that frequent words sit near the root, with short paths (a Huffman tree).

      Way 3 · Subsampling — fewer "the"s. "The" appears millions of times, and after the first thousand it teaches almost nothing about chai. So word2vec simply skips most of them. Each occurrence of a word with frequency ff (its share of all the words) is kept with probability

      P(keep)=t/f,t=10−5,P(\text{keep})=\sqrt{t/f},\qquad t=10^{-5},

      and always kept if f≤tf\le t. A word with f=4×10−5f=4\times10^{-5} is kept half the time (0.25=0.5)(\sqrt{0.25}=0.5); "the", with f=0.05f=0.05, only 1.4% of the time (0.0002≈0.0141)(\sqrt{0.0002}\approx0.0141); rare words are never dropped. Two gains: training is faster, and with the "the"s gone, a window of 2 words reaches further — to words that actually carry meaning.

      Three ways to make it cheapEvery dot is one word of the vocabulary: a full softmax lights them all for every guess, negative sampling only k+1k+1. The tree answers with a few left/right decisions. Subsampling thins out the common words before training even starts.

      Try: At 50 000 words and k=5k=5 negative sampling does about 8 333 times less work. Push the vocabulary to a million: the softmax grows twenty-fold, negative sampling stays at 6, and the tree grows only from 16 to 20 decisions. On the tree tab click each leaf: its path lights up and its chance is the product of the forks — chai 0.276, coffee 0.455 — and the four add up to 1. On subsampling press draw again: "the" and "and" mostly vanish, rare words always stay, and chai's window of ±2 reaches new words.

      50,000
      5

      Side by side:

      full softmaxnegative samplinghierarchical softmax
      the questionwhich one, out of everybody?this one — real or random? (k+1k+1 times)left or right? (down a tree)
      work per guessVV (50 000)k+1k+1 (6)⌈log⁡2V⌉\lceil\log_2V\rceil (16)
      true chances that add up to 1?yesno — a yes/no score per pairyes
      tends to suitsmall vocabulariesfrequent words; the usual defaultrare words

      Rule of thumb: negative sampling is the default (kk of about 5–20 for small collections of text, 2–5 for huge ones), hierarchical softmax is worth trying when rare words matter most, and subsampling is switched on in both.

      Why does this work?

      The knowledge was never in the sum over 50 000 words. It is in the pulls: toward the true neighbour, away from what is not a neighbour. Negative sampling keeps the pull toward the truth and replaces "away from everybody" by "away from a few random somebodies" — and over millions of steps every word gets its turn to be the random one. The tree keeps exact chances by splitting them fork by fork. And subsampling drops only the repeats that would have taught nothing new.

      Trap

      A model trained with negative sampling no longer gives you "the chance of each next word" — it learned a yes/no detector for pairs. Its vectors are excellent, but its scores are not probabilities that add up to 1. If you need real chances, as a language model does (§14), you need the full softmax or the tree.

      The realization

      LNS=−ln⁡σ(u+⋅v)−∑negativesln⁡σ(−u−⋅v)\begin{aligned}L_{\text{NS}}=&-\ln\sigma(\mathbf u_{+}\cdot\mathbf v)\\ &-\sum_{\text{negatives}}\ln\sigma(-\mathbf u_{-}\cdot\mathbf v)\end{aligned}

      Three tricks made word2vec cheap: ask k+1k+1 yes/no questions instead of scoring all VV words (negative sampling), walk log⁡2V\log_2V forks of a tree (hierarchical softmax), and skip most copies of very common words (subsampling). The cost of a guess stops growing with the vocabulary.

      Pause & predict

      The vocabulary has 100 000 words and you use k=10k=10 negatives. About how many times fewer dot products does one guess need?

      Pause & predict

      A hierarchical softmax is built as a balanced tree over a vocabulary of one million words. How many left/right decisions does one guess need?

      Pause & predict

      In the worked round, after one step with η=1\eta=1, what happens to the score ufootball⋅vchai\mathbf u_{\text{football}}\cdot\mathbf v_{\text{chai}}?

      If you want the algebra · 5 proofs, step by step
      Prove it · the slope of −ln σ

      Claim. ddz(−ln⁡σ(z))=−(1−σ(z))\dfrac{d}{dz}\big(-\ln\sigma(z)\big)=-(1-\sigma(z)) and ddz(−ln⁡σ(−z))=σ(z)\dfrac{d}{dz}\big(-\ln\sigma(-z)\big)=\sigma(z).

      1
      The sigmoid's slope is σ′(z)=σ(z)(1−σ(z))\sigma'(z)=\sigma(z)(1-\sigma(z)) (proved in Unit 15). By the chain rule, ddz(−ln⁡σ(z))=−σ(z)(1−σ(z))σ(z)=−(1−σ(z)).\begin{aligned}&\frac{d}{dz}\big(-\ln\sigma(z)\big)\\ &=-\frac{\sigma(z)(1-\sigma(z))}{\sigma(z)}\\ &=-(1-\sigma(z)).\end{aligned} The "how wrong" of a real pair: 1 minus the confidence.
      2
      For the negative term, σ(−z)=1−σ(z)\sigma(-z)=1-\sigma(z), so by the chain rule (the inner slope is −1-1): ddz(−ln⁡σ(−z))=1−σ(−z)=σ(z).\begin{aligned}&\frac{d}{dz}\big(-\ln\sigma(-z)\big)\\ &=1-\sigma(-z)=\sigma(z).\end{aligned} ∎ The "how wrong" of a negative pair: how much the model still believed it was real.
      Prove it · the pull and push rules

      Claim. For L=−ln⁡σ(u+⋅v)−ln⁡σ(−u−⋅v)L=-\ln\sigma(\mathbf u_+\cdot\mathbf v)-\ln\sigma(-\mathbf u_-\cdot\mathbf v), with g+=1−σ(u+⋅v)g_+=1-\sigma(\mathbf u_+\cdot\mathbf v) and g−=σ(u−⋅v)g_-=\sigma(\mathbf u_-\cdot\mathbf v), a step of size η\eta downhill is u+←u++η g+ v,u−←u−−η g− v,v←v+η (g+u+−g−u−).\begin{aligned}\mathbf u_+&\leftarrow\mathbf u_++\eta\,g_+\,\mathbf v,\\ \mathbf u_-&\leftarrow\mathbf u_--\eta\,g_-\,\mathbf v,\\ \mathbf v&\leftarrow\mathbf v+\eta\,(g_+\mathbf u_+-g_-\mathbf u_-).\end{aligned}

      1
      The score z=u⋅vz=\mathbf u\cdot\mathbf v has slope v\mathbf v with respect to u\mathbf u, and u\mathbf u with respect to v\mathbf v (Unit 6). Chain it with the previous proof: ∂L∂u+=−g+v,∂L∂u−=g−v,∂L∂v=−g+u++g−u−.\begin{aligned}\frac{\partial L}{\partial\mathbf u_+}&=-g_+\mathbf v,\\ \frac{\partial L}{\partial\mathbf u_-}&=g_-\mathbf v,\\ \frac{\partial L}{\partial\mathbf v}&=-g_+\mathbf u_++g_-\mathbf u_-.\end{aligned} Local slope times incoming blame — Unit 7's rule.
      2
      A step downhill subtracts η\eta times each gradient, which flips the signs into the rules above. ∎ Worked: g+=g−=1−σ(0.5)≈0.378g_+=g_-=1-\sigma(0.5)\approx0.378, so v←(1,0)+0.378 ((0.5,0.5)−(−0.5,1))=(1.378,−0.189)\mathbf v\leftarrow(1,0)+0.378\,\big((0.5,0.5)-(-0.5,1)\big)=(1.378,-0.189).
      Prove it · a full softmax touches every word

      Claim. For L=−ln⁡softmax⁡(s)oL=-\ln\operatorname{softmax}(\mathbf s)_o with scores sw=uw⋅vs_w=\mathbf u_w\cdot\mathbf v, the gradient is ∂L/∂uw=(qw−yw) v\partial L/\partial\mathbf u_w=(q_w-y_w)\,\mathbf v for every word ww, where q\mathbf q is the softmax and y\mathbf y the one-hot truth.

      1
      From Unit 14: the blame on the scores of a softmax with cross-entropy is prediction minus truth, ∂L/∂sw=qw−yw\partial L/\partial s_w=q_w-y_w. The same "prediction minus truth" as Unit 15's output layer.
      2
      Each score depends on its own uw\mathbf u_w with slope v\mathbf v, so ∂L/∂uw=(qw−yw)v\partial L/\partial\mathbf u_w=(q_w-y_w)\mathbf v. Since qw>0q_w>0 for every word, every one of the VV output vectors gets a non-zero update. ∎ Negative sampling touches only k+1k+1 output vectors, so its cost does not grow with VV.
      Prove it · the leaves of the tree always add up to one

      Claim. If every fork sends a share σ(θ⋅h)\sigma(\boldsymbol\theta\cdot\mathbf h) of what reaches it to the left and σ(−θ⋅h)\sigma(-\boldsymbol\theta\cdot\mathbf h) to the right, the chances of all the leaves add up to 1 — without ever adding over the vocabulary.

      1
      The two branches of a fork share out exactly what arrives, because σ(z)+σ(−z)=11+e−z+e−z1+e−z=1.\begin{aligned}&\sigma(z)+\sigma(-z)\\ &=\frac{1}{1+e^{-z}}+\frac{e^{-z}}{1+e^{-z}}\\ &=1.\end{aligned} Multiply top and bottom of σ(−z)=1/(1+ez)\sigma(-z)=1/(1+e^{z}) by e−ze^{-z}.
      2
      The root starts with 1. Each fork splits its amount into two parts with the same total, so after every level the total is still 1. The leaves are the last level. ∎ Our tree: 0.2760+0.4551+0.0723+0.1966=10.2760+0.4551+0.0723+0.1966=1. A leaf at depth DD costs DD sigmoids, and a balanced tree over VV words has depth ⌈log⁡2V⌉\lceil\log_2V\rceil.
      Prove it · subsampling turns counts into square roots

      Claim. After subsampling, a word that makes up a share f>tf>t of the text makes up about t f\sqrt{t\,f} of it. So a word 100 times more common than another keeps only 10 times as many copies.

      1
      Each copy survives with chance t/f\sqrt{t/f}, so on average the surviving share is f⋅t/f=t f.f\cdot\sqrt{t/f}=\sqrt{t\,f}. Expected value: share of copies times the chance each survives.
      2
      For two words with f1=100 f2f_1=100\,f_2 (both above tt): t⋅100f2/t f2=100=10\sqrt{t\cdot100f_2}\big/\sqrt{t\,f_2}=\sqrt{100}=10. ∎ "The" (f=0.05f=0.05) is 1 250 times as common as a word with f=4×10−5f=4\times10^{-5}; after subsampling it is only 1250≈35.4\sqrt{1250}\approx35.4 times as common.

      In one sentence: A full softmax scores all VV words for every guess; negative sampling asks k+1k+1 yes/no questions (50 000 against 6), a tree asks ⌈log⁡2V⌉\lceil\log_2V\rceil left/right questions (16), and subsampling keeps each "the" with chance only t/f\sqrt{t/f} — together they made training on billions of words possible.

      13

      Why it works: counting and predicting meet

      Counting a table and playing a guessing game look nothing alike. Why do they end up with such similar word vectors?

      Imagine this

      Two strangers in a new city. They have never met. But they shop at the same kirana store, buy vegetables from the same cart and ride the same bus. After a month, look into their bags: the same brand of tea, the same bread, the same bus pass.

      Nobody introduced them. The same places filled their bags with the same things.

      That is word2vec in one picture. Every time a word appears, its vector is pulled toward the vectors of its neighbours. Two words that keep the same company — even if they never once appear together — receive the same pulls, step after step. So their vectors are pulled to the same place. Watch it happen: in the demo below, chai and coffee never share a sentence, but they share their neighbours.

      Strangers who shop at the same storesSkip-gram with negative sampling, trained live on made-up sentences in which chai and coffee never meet but keep the same company; wicket keeps cricket company. Each word is a dot on the globe (only its direction counts). Only the three words of the story are named — point at any other dot to read it.

      Try: Press ▶ train. Watch the cosine of chai and coffee climb to nearly 1 while the loss drops — and chai and wicket, who keep different company, stay far apart. Press new start: the dots begin somewhere else, but chai and coffee always end together (above 0.99 from every start we tried). Try 1 negative against 10.

      drag the picture to orbit · point at a dot to read it

      5

      The surprise: word2vec is secretly counting. In 2014 Omer Levy and Yoav Goldberg asked what skip-gram with negative sampling is aiming for, if its vectors had room to give every pair exactly the score it wants. The answer: for every word ww and context word cc, it wants

      uc⋅vw=PMI⁡(w,c)−ln⁡k.\mathbf u_c\cdot\mathbf v_w=\operatorname{PMI}(w,c)-\ln k.

      The best possible score for a pair is exactly the PMI of §6 (in natural logs), shifted down by ln⁡k\ln k. For chai and hot, PMI⁡=ln⁡1.6≈0.470\operatorname{PMI}=\ln1.6\approx0.470; with k=5k=5 negatives the best score is 0.470−ln⁡5≈−1.1390.470-\ln5\approx-1.139. So a table of dot products u⋅v\mathbf u\cdot\mathbf v is a squeezed copy of the PMI table: word2vec is quietly doing what §6 and §7 did by hand — weigh the company, then squeeze it. The counting road and the predicting road arrive at the same city.

      GloVe makes the meeting explicit. In 2014 Jeffrey Pennington, Richard Socher and Christopher Manning at Stanford built a method straight on this idea, called GloVe (global vectors). Their insight: meaning lives in ratios of co-occurrence probabilities. Take chai and lassi, with 1 000 context words counted around each:

      probe word kkhotcolddrinkcricket
      P(k∣chai)P(k\mid\text{chai})40/10002/100060/10004/1000
      P(k∣lassi)P(k\mid\text{lassi})2/100040/100060/10004/1000
      ratio200.0511

      Words that tell chai and lassi apart give ratios far from 1: "hot" (20) points to chai, "cold" (0.05) to lassi. Words that do not tell them apart give 1, whether they are shared ("drink") or irrelevant to both ("cricket"). The GloVe paper found exactly this pattern for ice and steam with the probes solid and gas, counted over six billion words.

      So GloVe asks the vectors to reproduce the log counts directly, for every pair of words i,ji,j seen together XijX_{ij} times:

      wi⋅w~j+bi+b~j≈ln⁡Xij.\mathbf w_i\cdot\tilde{\mathbf w}_j+b_i+\tilde b_j\approx\ln X_{ij}.

      Then differences of vectors turn ratios into dot products: (wchai−wlassi)⋅w~hot≈ln⁡20≈2.996(\mathbf w_{\text{chai}}-\mathbf w_{\text{lassi}})\cdot\tilde{\mathbf w}_{\text{hot}}\approx\ln20\approx2.996. Each pair is weighted by f(Xij)=(Xij/100)3/4f(X_{ij})=(X_{ij}/100)^{3/4} (and 1 above 100), so rare, noisy counts matter less: f(40)≈0.503f(40)\approx0.503, f(2)≈0.053f(2)\approx0.053.

      Meaning lives in ratiosLeft: for the chosen probe word, how often it appears around chai and around lassi, and their ratio on a log scale. Right: vectors hand-made to satisfy GloVe's rule — the difference arrow chai − lassi and one arrow per probe word.

      Try: Pick hot: ratio 20, ln 20 ≈ 3.0, and the difference arrow points toward hot. Pick cold: 0.05, and it points away. Pick drink or cricket: ratio 1, ln 1 = 0 — those arrows stand at right angles to the difference, because they cannot tell chai from lassi.

      probe word
      Why does this work?

      Counting and predicting read the same thing — which words share windows — and both boil it down to the same kind of number: how much more often than chance a pair meets. Counting writes that number into a table and squeezes it; word2vec discovers it through billions of small pulls; GloVe fits it head-on. Different roads, same city, because the city is the company words keep.

      Trap

      "Predicting is smarter than counting" is a myth. With the same text, the same window and sensible settings (PPMI, a little smoothing, a good kk), well-tuned counting methods and word2vec produce vectors of very similar quality. The big wins of word2vec were speed and scale — it never has to build the giant table.

      The realization

      uc⋅vw→PMI⁡(w,c)−ln⁡k,wi⋅w~j+bi+b~j≈ln⁡Xij\begin{gathered}\mathbf u_c\cdot\mathbf v_w\to\operatorname{PMI}(w,c)-\ln k,\\ \mathbf w_i\cdot\tilde{\mathbf w}_j+b_i+\tilde b_j\approx\ln X_{ij}\end{gathered}

      Words that keep the same company receive the same pulls, so their vectors converge. At its best, word2vec's dot products equal the PMI of §6 shifted by ln⁡k\ln k — it is squeezing the counting table without ever writing it down — and GloVe fits the log counts directly, so that differences of vectors reproduce ratios of probabilities.

      Pause & predict

      In the demo, chai and coffee never appear in the same sentence. What happens to their cosine as training goes on?

      Pause & predict

      PMI⁡(chai,hot)=ln⁡1.6≈0.470\operatorname{PMI}(\text{chai},\text{hot})=\ln1.6\approx0.470. With only k=1k=1 negative per pair, what is the best score uhot⋅vchai\mathbf u_{\text{hot}}\cdot\mathbf v_{\text{chai}} skip-gram can aim for?

      Pause & predict

      The probe word "drink" is equally common around chai and around lassi. What does GloVe want the dot product (wchai−wlassi)⋅w~drink(\mathbf w_{\text{chai}}-\mathbf w_{\text{lassi}})\cdot\tilde{\mathbf w}_{\text{drink}} to be?

      If you want the algebra · 2 proofs, step by step
      Prove it · negative sampling aims at PMI − ln k

      Claim. Suppose the score x=uc⋅vwx=\mathbf u_c\cdot\mathbf v_w of each pair could be chosen freely. Then the negative-sampling loss is smallest at x=PMI⁡(w,c)−ln⁡kx=\operatorname{PMI}(w,c)-\ln k (natural log), when negatives are drawn in proportion to plain counts.

      1
      Over the whole text, (w,c)(w,c) appears n(w,c)n(w,c) times as a real pair. Word ww is the centre of n(w)n(w) pairs, and for each of them kk negatives are drawn, so cc turns up as a negative for ww about k n(w) n(c)/Nk\,n(w)\,n(c)/N times. The part of the loss that depends on xx is ℓ(x)=−n(w,c)ln⁡σ(x)−k n(w) n(c)N⋅ln⁡σ(−x).\begin{aligned}\ell(x)=&-n(w,c)\ln\sigma(x)\\ &-\tfrac{k\,n(w)\,n(c)}{N}\\ &\quad\cdot\ln\sigma(-x).\end{aligned} NN is the total number of pairs; n(c)/Nn(c)/N is the chance of drawing cc.
      2
      Set the slope to zero, using the slopes of −ln⁡σ-\ln\sigma from §12's drawer: −n(w,c)(1−σ(x))+k n(w) n(c)N σ(x)=0.\begin{aligned}&-n(w,c)\big(1-\sigma(x)\big)\\ &+\tfrac{k\,n(w)\,n(c)}{N}\,\sigma(x)=0.\end{aligned} Real pairs push xx up, negatives push it down; the best xx balances them.
      3
      Since σ(x)/(1−σ(x))=ex\sigma(x)/(1-\sigma(x))=e^{x}, this gives ex=n(w,c) Nk n(w) n(c)e^{x}=\dfrac{n(w,c)\,N}{k\,n(w)\,n(c)}, so x=ln⁡n(w,c) Nn(w) n(c)−ln⁡k=PMI⁡(w,c)−ln⁡k.\begin{aligned}x&=\ln\frac{n(w,c)\,N}{n(w)\,n(c)}-\ln k\\ &=\operatorname{PMI}(w,c)-\ln k.\end{aligned} ∎ Chai and hot: ln⁡1.6−ln⁡5≈0.470−1.609=−1.139\ln1.6-\ln5\approx0.470-1.609=-1.139. With the ¾-power noise of §12, the counts n(c)n(c) are simply smoothed. (Levy and Goldberg, 2014.)
      Prove it · in GloVe, a difference of vectors reads a ratio

      Claim. If wi⋅w~k+bi+b~k=ln⁡Xik\mathbf w_i\cdot\tilde{\mathbf w}_k+b_i+\tilde b_k=\ln X_{ik} for every pair, then (wi−wj)⋅w~k=ln⁡XikXjk−(bi−bj)(\mathbf w_i-\mathbf w_j)\cdot\tilde{\mathbf w}_k=\ln\dfrac{X_{ik}}{X_{jk}}-(b_i-b_j).

      1
      Write the rule for ii and for jj with the same probe kk, and subtract. The probe's own bias b~k\tilde b_k cancels: (wi−wj)⋅w~k+bi−bj=ln⁡Xik−ln⁡Xjk.\begin{aligned}&(\mathbf w_i-\mathbf w_j)\cdot\tilde{\mathbf w}_k+b_i-b_j\\ &=\ln X_{ik}-\ln X_{jk}.\end{aligned} A difference of logs is the log of a ratio.
      2
      Chai and lassi were each counted with 1 000 context words, so Xik/Xjk=P(k∣i)/P(k∣j)X_{ik}/X_{jk}=P(k\mid i)/P(k\mid j), and equal biases are free to fit both rows. Then the difference arrow reads the log ratio directly. ∎ hot: ln⁡20≈2.996\ln20\approx2.996; cold: ln⁡0.05≈−2.996\ln0.05\approx-2.996; drink and cricket: ln⁡1=0\ln1=0 — at right angles to chai − lassi.

      In one sentence: Words that keep the same company get the same pulls and converge — strangers who shop at the same stores — and at its best word2vec makes u⋅v=PMI⁡−ln⁡k\mathbf u\cdot\mathbf v=\operatorname{PMI}-\ln k (chai–hot: 0.470 − ln 5 ≈ −1.139), while GloVe fits the log counts so that meaning shows up in ratios like hot's 20 for chai against lassi.

      14

      A neural language model

      Can we have both — word vectors that share what they learn, and real chances for the next word?

      Imagine this

      Mumbai's dabbawalas pass a lunch box along a relay. One picks it up, one sorts it, one carries it, one hands it over. Nobody does the whole job, but the box always arrives.

      A neural language model is a relay like that. Look up the words, glue them together, mix them in a small network, and hand over a chance for every possible next word.

      The count tables of §2 could not share anything between "chai" and "coffee". In 2003 — ten years before word2vec — Yoshua Bengio and his team built a model that could. It works in five steps:

      1. Look up. Keep a table EE with one row of dd numbers for each word — an embedding table. Look up the row of each previous word.
      2. Glue. Put the rows side by side into one longer list (people say concatenate). Two previous words with d=2d=2 give a list of 4.
      3. Mix. Pass it through a hidden layer, exactly as in Unit 15: h=tanh⁡(Wx+b)\mathbf h=\tanh(W\mathbf x+\mathbf b).
      4. Score every word. One more layer gives one score per word, and a softmax (Unit 14) turns the scores into chances.
      5. Learn. Train with cross-entropy and backprop (Unit 15). The blame flows all the way back into the rows of EE, so the table is learned too.

      The lookup is a matrix multiply. Write a word one-hot and multiply it by the table. With three words and d=2d=2:

      (010)(123456)=(34).\begin{pmatrix}0&1&0\end{pmatrix}\begin{pmatrix}1&2\\ 3&4\\ 5&6\end{pmatrix}=\begin{pmatrix}3&4\end{pmatrix}.

      The single 1 picks out row 2. So an embedding table is nothing new: it is the first layer's weight matrix, fed with one-hot inputs. Computers skip the multiply and just fetch the row — same answer, far less work. And it is the same object as word2vec's input table WinW_{\text{in}} (§8): word2vec is this model with the hidden layer removed, trained on a simpler game.

      One-hot times a table = fetch a rowA one-hot word (left) multiplies the embedding table (middle). Every row but one is multiplied by 0, so only one row survives.

      Try: Click each word in turn. Watch the 1 move and the matching row light up. Then press ▶ multiply slowly to see all the zero rows vanish.

      Now the whole relay. We trained a tiny model ourselves, for this page, on just seven sentences: "I drink hot chai .", "we drink hot chai .", "I drink hot coffee .", "we drink hot coffee .", "I play cricket .", "we play cricket .", "we play football .". It has a vocabulary of 10 words, embeddings of d=2d=2 numbers and 8 hidden neurons. Its whole brain is 150 numbers.

      Notice what it has never seen: "I play football". A count table would give it chance exactly 0. But "I" and "we" were used in the same places, so the model learned almost the same row for both. It gives football after "I play" a chance of about 0.256 — nearly what it gives after "we play" (0.258). That is sharing, and it is the whole point of word vectors.

      A tiny neural language model, every number visiblePick two previous words. Their rows are fetched, glued into 4 numbers, mixed by 8 hidden neurons and turned into a chance for each of the 10 words. The small map shows every word's learned row of 2 numbers.

      Try: Pick "drink" then "hot": chai and coffee share the top. Pick "I" then "play": cricket first, but football gets a real share (0.256) though the model never saw "I play football". In the map, find "I" and "we" sitting almost on top of each other.

      word 1
      word 2
      Why does this work?

      Because the table is shared by every sentence. When the model learns something after "we play", the blame flows into the row for "we"; since "I" was pushed to nearly the same row by the same kinds of sentences, what was learned about "we" also works for "I". Similar rows make similar guesses — so the model can give a sensible chance to a sentence it has never seen.

      Trap

      The embedding table is not an extra part bolted onto the network — it is the first layer's weights, learned by the same backprop. And this model still has the short memory of §2: it sees exactly two previous words, no more. Removing that fixed window is the job of Unit 17.

      The realization

      x=[ Ew1; Ew2 ],h=tanh⁡(Wx+b),P(⋅∣w1w2)=softmax⁡(Uh+c)\begin{aligned}\mathbf x&=[\,E_{w_1};\,E_{w_2}\,],\\ \mathbf h&=\tanh(W\mathbf x+\mathbf b),\\ P(\cdot\mid w_1w_2)&=\operatorname{softmax}(U\mathbf h+\mathbf c)\end{aligned}

      A neural language model is a Unit 15 network with a lookup table in front and a softmax at the end. The table is just the first layer's weights, learned by the same backprop — the same kind of table word2vec learns. Because similar words get similar rows, what the model learns about one word helps it with the others.

      Pause & predict

      A vocabulary has 4 words and E=(102011310222)E=\begin{pmatrix}1&0&2\\ 0&1&1\\ 3&1&0\\ 2&2&2\end{pmatrix}. What is (0,0,1,0) E(0,0,1,0)\,E?

      Pause & predict

      Our tiny model has V=10V=10 words, d=2d=2, two previous words and 8 hidden neurons. How many numbers does it learn? (Table, then hidden weights and biases, then output weights and biases.)

      If you want the algebra · 2 proofs, step by step
      Prove it · one-hot times a matrix picks a row

      Claim. If ei\mathbf e_i is the one-hot row vector with a 1 in slot ii, then eiE\mathbf e_iE is row ii of EE.

      1
      Entry jj of the product is ∑k(ei)kEkj\sum_k(\mathbf e_i)_kE_{kj}. Row times column, as in Unit 1.
      2
      Only k=ik=i has (ei)k=1(\mathbf e_i)_k=1; every other term is 0. So entry jj is EijE_{ij}: the product is row ii. ∎ A lookup table and a first layer fed with one-hot inputs are the same thing.
      Prove it · backprop only changes the rows you used

      Claim. If x=eiE\mathbf x=\mathbf e_iE and the blame arriving at x\mathbf x is g=∂L/∂x\mathbf g=\partial L/\partial\mathbf x, then ∂L/∂E=eiTg\partial L/\partial E=\mathbf e_i^{\mathsf T}\mathbf g: the gradient is zero except in row ii, which gets g\mathbf g.

      1
      This is Rule B of Unit 15: the gradient of a weight matrix is the incoming blame times the input — here an outer product of the one-hot input with the blame. Written for a row-vector input, the outer product is eiTg\mathbf e_i^{\mathsf T}\mathbf g.
      2
      eiTg\mathbf e_i^{\mathsf T}\mathbf g has row kk equal to (ei)k g(\mathbf e_i)_k\,\mathbf g: that is g\mathbf g for k=ik=i and zero otherwise. ∎ So a training step only moves the rows of the words in the example — cheap, even with a 50 000-row table.

      In one sentence: A neural language model looks up each previous word's row in an embedding table (one-hot × matrix = picking a row — the same table word2vec learns), glues the rows, mixes them in a hidden layer and ends with a softmax over the vocabulary, so similar words share what they learn and even unseen sentences get sensible chances.

      15

      The geometry of meaning

      If every word is a point, what does it mean to walk from "man" to "woman"?

      Imagine this

      A friend gives you directions: "From the station, walk 2 blocks north and 3 blocks east." Those directions are not tied to the station. Start from the temple and follow the same walk, and you land somewhere new — but in the same position relative to where you started.

      In a good word space, the step from "man" to "woman" is a walk like that. Start the same walk from "king".

      First, three rulers for "similar". We have met three ways to compare two lists of numbers. Take two tea-stall orders a=(2,1)\mathbf a=(2,1) (two cups of chai, one biscuit) and b=(4,2)\mathbf b=(4,2) — the same taste, just a bigger order — and a third customer who likes biscuits more, c=(1,2)\mathbf c=(1,2).

      • Dot product: a⋅b=10\mathbf a\cdot\mathbf b=10, a⋅c=4\mathbf a\cdot\mathbf c=4. It mixes taste with size: bigger orders give bigger numbers.
      • Distance: ∥a−b∥=22+12≈2.236\lVert\mathbf a-\mathbf b\rVert=\sqrt{2^2+1^2}\approx2.236 but ∥a−c∥=12+12≈1.414\lVert\mathbf a-\mathbf c\rVert=\sqrt{1^2+1^2}\approx1.414. Distance says a\mathbf a is closer to c\mathbf c — the size difference beats the taste. (With an office order of (20, 10) it gets worse: about 20.12 against 1.414.)
      • Cosine: cos⁡(a,b)=1\cos(\mathbf a,\mathbf b)=1 exactly (the same direction), cos⁡(a,c)=4/5=0.8\cos(\mathbf a,\mathbf c)=4/5=0.8. The cosine sees only taste.

      For word vectors, the length mostly tracks how often a word appears, and the direction tracks what it means — so the cosine is the standard ruler. To make the three rulers agree, normalise: shrink or stretch every vector to length 1. Then the dot product is the cosine, and distance follows from it, ∥a^−b^∥2=2−2cos⁡θ\lVert\hat{\mathbf a}-\hat{\mathbf b}\rVert^2=2-2\cos\theta, so all three rulers rank neighbours the same way. Real systems normalise once and then use fast dot products.

      Three rulers for "similar"Drag the tips of the two arrows. The dot product, the cosine (with its angle) and the distance update together.

      Try: Start with the two shoppers: cosine exactly 1, distance 2.236. Drag b\mathbf b further out along the same line: the cosine stays 1 while the distance grows. Swing it to a right angle: cosine 0. Then press normalise: both arrows snap to length 1, and the distance becomes 2−2cos⁡θ\sqrt{2-2\cos\theta}.

      Now the walk. Here are four hand-made vectors with just two numbers each (we built them for this example; they are not trained):

      king=(3,2),man=(1,2),queen=(3,−2),woman=(1,−2).\begin{aligned}\text{king}&=(3,2), & \text{man}&=(1,2),\\ \text{queen}&=(3,-2), & \text{woman}&=(1,-2).\end{aligned}

      The step from man to woman is woman−man=(0,−4)\text{woman}-\text{man}=(0,-4). The step from king to queen is queen−king=(0,−4)\text{queen}-\text{king}=(0,-4) — the same step. The four points make a parallelogram, and that answers the puzzle "man is to woman as king is to ?":

      king−man+woman=(3,2)−(1,2)+(1,−2)=(3,−2).\begin{aligned}&\text{king}-\text{man}+\text{woman}\\ &=(3,2)-(1,2)+(1,-2)=(3,-2).\end{aligned}

      That is exactly queen. With real, trained vectors the answer is never exact; it lands near a word. So we search for the nearest word by cosine. For (3,−2)(3,-2): queen 1, woman 0.868, king 0.385, man −0.124.

      Skip the three words you started with. In trained vectors the step "woman − man" is short next to the words themselves, so the answer usually lies closest to king itself. A search that allowed king would just return king — true, but useless. So the search always leaves out the three input words.

      The parallelogram, by handDrag king, man or woman. The answer king − man + woman is drawn as the fourth corner, and the nearest word by cosine lights up.

      Try: Leave the points as they are: the corner lands exactly on queen. Drag woman a little: the corner moves the same way, and the nearest word stays queen until it drifts too far. Turn on include the inputs and drag man close to king — see why we skip them.

      A bigger playground. Below are 60 words. Their vectors are hand-made by us — not trained on text — so that you can check every answer with your own sense of meaning. Each word has 13 numbers: nine meanings we chose (is it a person? royal? female or male? young? a drink? about cricket? an animal? a place? a capital city?), four random "family fingerprint" numbers shared by a family such as king, queen, prince and princess, and a little random noise. The sums and the cosines use all 13 numbers.

      To draw them we look through a fixed 3-D window — a projection, like a shadow on a wall (Unit 3). A shadow of a parallelogram is still a parallelogram, so the picture never lies about the arithmetic. But lengths and angles do change in a shadow: two dots that look close may not be, so always read the cosines in the box, never the picture alone.

      How do people test real embeddings? Two ways. Similarity: people rate pairs of words — chai and coffee, cup and kettle — and we check whether the cosines put the pairs in the same order. Analogies: thousands of puzzles like "Delhi is to India as Tokyo is to ?", and we count how often the nearest word to A−B+CA-B+C is the right one.

      The embedding explorerSixty hand-made words in space, drawn as dots. Choose A−B+CA-B+C: the parallelogram draws itself, the three words and the answer are named, and the nearest words by cosine are listed. Point at any dot to read its word, or turn on the direction arrows.

      Try: Start with king − man + woman. Then try the others: prince − boy + girl, Delhi − India + Japan, puppy − dog + cat. Turn on the female arrows — nearly the same arrow at every pair. Type any word in the search box to fly to it and list its neighbours.

      − + ≈?

      drag the picture to orbit · point at a dot to read it

      direction arrows
      Why does this work?

      Think of what separates "king" from "queen" in text: the same small change of company — "he", "his", "sir" around one; "she", "her", "madam" around the other — while the royal company (crown, palace, throne) stays. Man and woman differ by that same change. If the same change of company always moves a vector the same way, it becomes the same arrow everywhere, and adding it to king swaps king's "he" company for "she" company while keeping the crown.

      Trap

      Analogies are less magical than they look. On real vectors, king − man + woman lands nearest to king itself; many famous analogies only "work" because the three inputs are skipped. And a picture of word vectors is always a shadow: never trust how close two dots look — trust the cosine.

      The realization

      q=va−vb+vc,answer=arg⁡max⁡w∉{a,b,c} cos⁡(vw,q)\begin{gathered}\mathbf q=\mathbf v_a-\mathbf v_b+\mathbf v_c,\\ \text{answer}=\arg\max_{w\notin\{a,b,c\}}\ \cos(\mathbf v_w,\mathbf q)\end{gathered}

      In a good word space, closeness (by cosine) is similarity and a difference of meanings is a direction. The same arrow turns man into woman, king into queen and boy into girl; another turns a country into its capital. "B is to C as A is to ?" becomes arithmetic: A−B+CA-B+C, then the nearest word by cosine, leaving out AA, BB and CC.

      Pause & predict

      Toy vectors: Delhi =(1,1,3)=(1,1,3), India =(1,0,3)=(1,0,3), Japan =(3,0,1)=(3,0,1). What is Delhi − India + Japan?

      Pause & predict

      Why does the analogy search leave out the three input words?

      Pause & predict

      Two vectors of length 1 have cosine 0.5. How far apart are their tips?

      Pause & predict

      A word vector is a=(3,4)\mathbf a=(3,4). The same word counted over twice as much text gives b=(6,8)\mathbf b=(6,8). What do the dot product, the cosine and the distance say?

      If you want the algebra · 2 proofs, step by step
      Prove it · a shadow keeps parallelograms

      Claim. If d=a−b+c\mathbf d=\mathbf a-\mathbf b+\mathbf c (so b,a,d,c\mathbf b,\mathbf a,\mathbf d,\mathbf c make a parallelogram) and f(x)=Px+tf(\mathbf x)=P\mathbf x+\mathbf t is any projection plus shift, then f(d)=f(a)−f(b)+f(c)f(\mathbf d)=f(\mathbf a)-f(\mathbf b)+f(\mathbf c).

      1
      Expand, using that a matrix spreads over sums: f(a)−f(b)+f(c)=Pa−Pb+Pc+(t−t+t)=P(a−b+c)+t=f(d).\begin{aligned}&f(\mathbf a)-f(\mathbf b)+f(\mathbf c)\\ &=P\mathbf a-P\mathbf b+P\mathbf c\\ &\quad+(\mathbf t-\mathbf t+\mathbf t)\\ &=P(\mathbf a-\mathbf b+\mathbf c)+\mathbf t\\ &=f(\mathbf d).\end{aligned} ∎ That is why the explorer can draw 13-number vectors in 3-D without breaking the parallelograms. Lengths and angles do change in a shadow, so cosines are always computed on all 13 numbers.
      Prove it · for unit vectors, distance is a cosine in disguise

      Claim. If ∥a^∥=∥b^∥=1\lVert\hat{\mathbf a}\rVert=\lVert\hat{\mathbf b}\rVert=1, then ∥a^−b^∥2=2−2cos⁡θ\lVert\hat{\mathbf a}-\hat{\mathbf b}\rVert^2=2-2\cos\theta.

      1
      Expand the square with the dot product: ∥a^−b^∥2=a^⋅a^−2 a^⋅b^+b^⋅b^=1−2cos⁡θ+1.\begin{aligned}&\lVert\hat{\mathbf a}-\hat{\mathbf b}\rVert^2\\ &=\hat{\mathbf a}\cdot\hat{\mathbf a}-2\,\hat{\mathbf a}\cdot\hat{\mathbf b}+\hat{\mathbf b}\cdot\hat{\mathbf b}\\ &=1-2\cos\theta+1.\end{aligned} ∎ The distance grows exactly as the cosine shrinks, so the nearest word by distance is the nearest by cosine. At cos⁡θ=0.5\cos\theta=0.5: distance 1.

      In one sentence: Measure "similar" by the cosine (after normalising, all three rulers agree), and a difference of meanings becomes a direction — king − man + woman = (3, −2) = queen in our toy plane, and with real vectors we take the nearest word by cosine, leaving out the three words we started from.

      16

      What one vector per word gets wrong — and how pieces help

      What should a machine do with a word that means two things — or with a word it has never seen?

      Imagine this

      "He hit a six with his bat." "A bat flew out of the old fort at dusk." Same word, two completely different things. You never mix them up, because the sentence tells you which one is meant.

      And when a shopkeeper says "ask the chaiwala", you understand at once — though you may never have heard that exact word — because you know its pieces.

      Problem 1 · one vector must blend every meaning. Everything so far gives each word one vector, whatever the sentence. So what does "bat" get? Training pulls it toward cricket words every time it appears in a cricket sentence and toward animal words every time it appears in an animal sentence. It ends up roughly a blend, weighted by how often each meaning is used.

      A tiny example. Let the cricket meaning point along (1,0)(1,0) and the animal meaning along (0,1)(0,1). If 80% of the sentences with "bat" are about cricket, the single vector is about

      0.8 (1,0)+0.2 (0,1)=(0.8, 0.2).0.8\,(1,0)+0.2\,(0,1)=(0.8,\ 0.2).

      Its cosine with the cricket meaning is 0.8/0.68≈0.9700.8/\sqrt{0.68}\approx0.970, and with the animal meaning only 0.2/0.68≈0.2430.2/\sqrt{0.68}\approx0.243. The rare meaning is almost drowned. A word used half and half sits in the middle, close to neither group.

      Problem 2 · vectors copy the text they learn from. The vectors are a mirror of how words are used in the corpus — nothing more. If the training text more often writes "the doctor … he" and "the nurse … she", then "doctor" leans toward the male end of the female–male direction and "nurse" toward the female end. That is a fact about the text, not about doctors or nurses. It matters because a system built on these vectors will repeat the pattern. People measure such leanings with directions like the ones in §15. They can also remove such a direction from every vector, but that hides only part of the pattern, so the text itself still matters.

      Problem 3 · words never seen get no vector at all. A table has one row per word it met in training. A new word — a spelling mistake, a new brand, "chaiwala" — has no row, and a plain word2vec model can say nothing about it.

      The word with two livesThe cricket words and the animal words from the explorer, drawn as dots (point at one to read it). "bat" gets one vector: a blend of both meanings. Slide how often it is used in cricket sentences and watch it travel; its three nearest words are named.

      Try: Slide to 100%: bat sits in the cricket group. Slide to 0%: among the animals. At 50% it sits in the empty space between, and its nearest neighbours are weak (best cosine about 0.69). Then press the two sentence buttons for a peek at Unit 18: a vector that moves with its sentence.

      drag the picture to orbit · point at a dot to read it

      50%

      The fix for unseen words: pieces. In 2017 Piotr Bojanowski and colleagues at Facebook built fastText, a word2vec in which a word's vector is the sum of the vectors of its pieces. The pieces are short runs of letters called character n-grams, taken after marking the start and end of the word with < and >. With pieces of 3 letters:

      <chai> → <ch cha hai ai>

      <chaiwala> → <ch cha hai aiw iwa wal ala la>

      "chaiwala" shares 3 pieces with "chai" (<ch, cha, hai) and 3 with "dudhwala" (wal, ala, la>). So even though "chaiwala" was never seen, adding up its pieces gives it a sensible vector — near chai, and near the other -walas. (Real fastText uses pieces of 3 to 6 letters, plus the whole word.)

      How modern language models cut text: byte-pair encoding. Big language models go one step further and choose their pieces from data. Start with single characters. Count every pair of neighbouring symbols across the corpus, merge the most frequent pair into one new symbol, and repeat. Take a corpus with the words hug (10 times), pug (5), pun (12), bun (4) and hugs (5):

      1. u + g appears 10 + 5 + 5 = 20 times → merge into "ug".
      2. u + n appears 12 + 4 = 16 times → "un".
      3. h + ug appears 10 + 5 = 15 times → "hug".
      4. p + un appears 12 times → "pun".

      After these four merges, "hugs" is cut as hug · s, and a word never seen, "bug", as b · ug. When two pairs tie, we merge the one met first in reading order. Frequent words become single tokens, and rare words are spelled out of common pieces — so nothing is ever unknown. This is byte-pair encoding (BPE). Most large language models cut their text this way, or with a close cousin of it, and the pieces of Unit 19 are made like this.

      Words in piecesfastText: type a word and see its 3-letter pieces; pieces it shares with known words light up. BPE: step through the merges on the small corpus, then cut any word you type with the merges learned so far.

      Try: Type chaiwala: it shares 3 pieces with chai, 3 with dudhwala and 4 with sabziwala. Press kadakchai: 4 pieces from kadak, 3 from chai. Then look at chain in the list — 3 pieces shared with chai, and no meaning shared at all. In BPE, press next merge four times — u+g (20), u+n (16), h+ug (15), p+un (12) — then cut hugs and bug.

      Why does this work?

      Pieces are shared. A rare word is almost always made of common pieces, and a common piece has been seen thousands of times inside other words, so its vector is well trained. Adding up well-trained pieces gives even an unseen word a vector in the right neighbourhood — the way you understood "chaiwala" from "chai" and "-wala".

      Trap

      Pieces are not meanings. "chai" and "chain" share <ch, cha and hai, yet have nothing in common. Pieces help because, over many words, pieces like "wala", "ing" or "un" really do carry meaning — for any single word they can mislead. And pieces do nothing for "bat": both meanings are spelled the same. Only the sentence can tell them apart, which is where Unit 18 goes: every word gets a new vector computed from its sentence, so "bat" in a cricket sentence and "bat" in a fort get different vectors.

      The realization

      vbat≈s vcricket+(1−s) vanimal,vword=∑pieces gzg\begin{gathered}\mathbf v_{\text{bat}}\approx s\,\mathbf v_{\text{cricket}}+(1-s)\,\mathbf v_{\text{animal}},\\ \mathbf v_{\text{word}}=\sum_{\text{pieces }g}\mathbf z_g\end{gathered}

      One vector per word must blend all its meanings (weighted by use), copies the patterns of its text, and has nothing to say about unseen words. Pieces fix the unseen words — fastText adds up character n-grams, BPE learns a vocabulary of frequent pieces — but only a vector that changes with its sentence can fix "bat".

      Pause & predict

      A word is used in its first meaning (1,0)(1,0) half the time and in its second meaning (0,1)(0,1) half the time. Its single vector is the blend (0.5,0.5)(0.5,0.5). What is its cosine with each meaning?

      Pause & predict

      With 3-letter pieces, how many pieces does "<chais>" share with "<chai>"?

      Pause & predict

      After the four BPE merges (u+g, u+n, h+ug, p+un), how is the new word "bug" cut?

      If you want the algebra · 2 proofs, step by step
      Prove it · a blend leans toward its common meaning

      Claim. If the two meanings are unit vectors at right angles, m1⊥m2\mathbf m_1\perp\mathbf m_2, and a word is used in meaning 1 a share ss of the time, its blend b=s m1+(1−s) m2\mathbf b=s\,\mathbf m_1+(1-s)\,\mathbf m_2 has cos⁡(b,m1)=ss2+(1−s)2\cos(\mathbf b,\mathbf m_1)=\dfrac{s}{\sqrt{s^2+(1-s)^2}}.

      1
      The dot product keeps only the part along m1\mathbf m_1: b⋅m1=s\mathbf b\cdot\mathbf m_1=s, because m1⋅m1=1\mathbf m_1\cdot\mathbf m_1=1 and m2⋅m1=0\mathbf m_2\cdot\mathbf m_1=0. Right angles make the cross term vanish.
      2
      By Pythagoras, ∥b∥=s2+(1−s)2\lVert\mathbf b\rVert=\sqrt{s^2+(1-s)^2}. Divide. ∎ s=0.8s=0.8: 0.8/0.68≈0.9700.8/\sqrt{0.68}\approx0.970 with cricket and 0.2/0.68≈0.2430.2/\sqrt{0.68}\approx0.243 with the animal. s=0.5s=0.5: 0.5/0.5≈0.7070.5/\sqrt{0.5}\approx0.707 with each.
      Prove it · a word of L letters has L pieces of 3

      Claim. With the markers < and > added, a word of LL letters has exactly LL character 3-grams.

      1
      With the two markers the string has L+2L+2 characters. A window of 3 can start at positions 1,2,…,(L+2)−3+11,2,\dots,(L+2)-3+1. The last window must end on the last character.
      2
      That is (L+2)−3+1=L(L+2)-3+1=L windows. ∎ chai: 4 pieces; chaiwala: 8 pieces, 3 of them shared with chai. Common endings like "wala" or "ing" become pieces shared by many words.

      In one sentence: One vector per word blends every meaning of that word (80% cricket gives cosines 0.970 and 0.243), copies the patterns of its text and knows nothing of unseen words — pieces fix the unseen words (chaiwala shares 3 pieces with chai; BPE cuts bug as b · ug), and Unit 18's vectors that change with the sentence fix the rest.

      17

      What to carry forward

      The whole unit fits on one wall of cards. Each card is one picture to keep.

      A label, then a map

      One-hot lists are a phone directory: every pair of words at right angles and 2\sqrt2 apart. We want a map, where close means similar.

      A chain of guesses

      P(w1⋯wn)=∏tP(wt∣history)P(w_1\cdots w_n)=\prod_tP(w_t\mid\text{history}); a short memory (bigram, trigram) and count ÷ total; ⟨s⟩\langle s\rangle, ⟨/s⟩\langle/s\rangle start and stop the chain.

      Never seen ≠ impossible

      Smoothing moves a little probability to unseen pairs. Add-one drowns real counts in a big vocabulary; interpolation and backoff ask a more general adviser.

      Perplexity

      2average surprise2^{\text{average surprise}}: how many faces the model's die has. 1 is perfect, VV is clueless; compare only on the same test text.

      The company a word keeps

      A row of neighbour counts is a vector; similar = cosine near 1. Small windows find stand-ins, big windows topic-mates.

      Weigh by surprise

      PMI =log⁡2P(w,c)P(w)P(c)=\log_2\frac{P(w,c)}{P(w)P(c)} and TF-IDF give "the" the weight 0. Beware rare pairs.

      Squeeze: friends of friends

      Keep the top kk singular directions (rows of UkΣkU_k\Sigma_k). Shared directions make chai and tea friends through coffee.

      CBOW: the committee

      Average the context vectors, softmax over the vocabulary, error = prediction − truth, blame shared 12C\tfrac1{2C} each.

      Skip-gram: one word, many guesses

      One softmax checked against every neighbour; the centre gets the full sum of the blame — good for rare words.

      Three ways to make it cheap

      Negative sampling (k+1k+1 yes/no questions), hierarchical softmax (log⁡2V\log_2V forks), subsampling (keep each copy with t/f\sqrt{t/f}).

      Counting meets predicting

      Same company, same pulls, same place. At best u⋅v=PMI⁡−ln⁡k\mathbf u\cdot\mathbf v=\operatorname{PMI}-\ln k; GloVe fits log counts so ratios become directions.

      A neural language model

      Look up (one-hot × table = a row), glue, hidden layer, softmax. The table is the first layer — the same kind of table word2vec learns.

      Meaning is a direction

      A−B+CA-B+C, then the nearest word by cosine, skipping A,B,CA,B,C. Pictures are shadows; trust the cosine.

      Limits, and pieces

      One vector blends every meaning and copies its text. Pieces (fastText, BPE) handle unseen words; context handles "bat".

      Where this goes next.

      • Unit 17 · Machines with Memory. Every model here saw a fixed window of words. A recurrent network reads a sentence one word at a time and carries a running memory along, so it can use everything before — and the fading or exploding of that memory becomes an eigenvalue story (Unit 4).
      • Unit 18 · Attention and Transformers. The fix for "bat" and "bank": every word looks at every other word in its sentence, using the very dot products of this unit, and takes on a new vector that fits its context.
      • Unit 19 · The Maths Inside an LLM (coming soon). A softmax over a whole vocabulary of BPE pieces, at the scale of billions of words — the cost problem of §12, met head-on.
      The realization

      king−man+woman≈queen\text{king}-\text{man}+\text{woman}\approx\text{queen}

      A word becomes a point in space, placed by the company it keeps — counted, weighed and squeezed, or learned by a guessing game, which turns out to be the same thing. In that space, closeness is similarity and a difference of meaning is a direction. Every language model you will meet from here on starts by turning its words, or pieces of words, into such vectors.

      In one sentence: Give each word a short list of numbers learned from the company it keeps — by counting, weighing and the SVD, or by word2vec's two guessing games, which secretly do the same — and meaning becomes geometry: similar words point the same way and differences of meaning are directions.

      18

      Practice arena — sixteen problems, solved in full

      Sixteen problems, easy to hard, one or more for every idea of the unit: chains of guesses, smoothing, perplexity, TF-IDF, PMI, cosines, the SVD squeeze, counting training examples, a CBOW pass, a skip-gram pass, a negative-sampling step, a path down a tree, subsampling, GloVe ratios, BPE merges and an analogy. Some run forwards, some backwards (find the setting that gives a result), and one asks you to judge two recorded models. Every number was checked by machine.

      Three habits do most of the work. Write the counts or vectors in a small table first. Turn probabilities into surprises before you average them. And for "similar", divide by the lengths: use the cosine, not the raw dot product.

      Problem 1easya chain of guesses

      The corpus is "we play cricket", "we play football", "we watch cricket", and a bigram model adds ⟨s⟩\langle s\rangle and ⟨/s⟩\langle/s\rangle to every sentence. (a) Give P(we∣⟨s⟩)P(\text{we}\mid\langle s\rangle), P(play∣we)P(\text{play}\mid\text{we}), P(cricket∣play)P(\text{cricket}\mid\text{play}) and P(⟨/s⟩∣cricket)P(\langle/s\rangle\mid\text{cricket}). (b) What chance does the model give ⟨s⟩\langle s\rangle we play cricket ⟨/s⟩\langle/s\rangle? (c) And ⟨s⟩\langle s\rangle we watch football ⟨/s⟩\langle/s\rangle? (d) List every sentence the model can produce with a chance above 0, and add up their chances.

      What this tests. The chain rule with a one-word memory, count ÷ total, and why the end marker makes the chances of all sentences add up to 1. Plan. Make the table of next-word counts for every history, then multiply along each sentence.

      Show the full solution
      Step 1 — the counts. After ⟨s⟩\langle s\rangle: we 3. After we: play 2, watch 1. After play: cricket 1, football 1. After watch: cricket 1. After cricket: ⟨/s⟩\langle/s\rangle 2. After football: ⟨/s⟩\langle/s\rangle 1.
      Step 2 — (a). P(we∣⟨s⟩)=3/3=1P(\text{we}\mid\langle s\rangle)=3/3=1, P(play∣we)=2/3P(\text{play}\mid\text{we})=2/3, P(cricket∣play)=1/2P(\text{cricket}\mid\text{play})=1/2, P(⟨/s⟩∣cricket)=2/2=1P(\langle/s\rangle\mid\text{cricket})=2/2=1.
      Step 3 — (b). Multiply along the chain: 1⋅23⋅12⋅1=131\cdot\tfrac23\cdot\tfrac12\cdot1=\tfrac13.
      Step 4 — (c). "watch" was only ever followed by cricket, so P(football∣watch)=0P(\text{football}\mid\text{watch})=0, and one zero makes the whole sentence 0.
      Step 5 — (d). From "we" the chain can go to play or watch; from play to cricket or football; from watch only to cricket; then it must stop. Three sentences: we play cricket (13\tfrac13), we play football (1⋅23⋅12⋅1=131\cdot\tfrac23\cdot\tfrac12\cdot1=\tfrac13), we watch cricket (1⋅13⋅1⋅1=131\cdot\tfrac13\cdot1\cdot1=\tfrac13). Total: 1.

      answers at a glance: (a) 1, 2/32/3, 1/21/2, 1. (b) 1/31/3. (c) 0. (d) three sentences, 1/31/3 each, total 1.

      Remember

      With the end marker, a bigram model shares out exactly 1 among all the sentences it can write.

      Problem 2mediumsmoothing

      Same corpus as Problem 1. The possible next words are we, play, watch, cricket, football and ⟨/s⟩\langle/s\rangle (V=6V=6). (a) With add-one smoothing, give P(cricket∣play)P(\text{cricket}\mid\text{play}) and P(watch∣play)P(\text{watch}\mid\text{play}). (b) The unigram adviser counts the 12 tokens that follow the ⟨s⟩\langle s\rangle markers. With interpolation 0.7 Pbigram+0.3 Punigram0.7\,P_{\text{bigram}}+0.3\,P_{\text{unigram}}, give the same two chances. (c) Which weight λ\lambda on the bigram would make P(watch∣play)P(\text{watch}\mid\text{play}) exactly 0.05? (d) Show that the interpolated row for "play" adds up to 1 whatever λ\lambda is.

      What this tests. Add-one, interpolation, and running interpolation backwards. Plan. Write the "play" row (cricket 1, football 1, total 2) and the unigram counts first.

      Show the full solution
      Step 1 — (a). Add 1 to each count and V=6V=6 to the total: P(cricket∣play)=1+12+6=0.25P(\text{cricket}\mid\text{play})=\tfrac{1+1}{2+6}=0.25, P(watch∣play)=0+12+6=0.125P(\text{watch}\mid\text{play})=\tfrac{0+1}{2+6}=0.125.
      Step 2 — the unigram counts. we 3, play 2, watch 1, cricket 2, football 1, ⟨/s⟩\langle/s\rangle 3: 12 tokens.
      Step 3 — (b). P(cricket∣play)=0.7⋅12+0.3⋅212=0.35+0.05=0.4P(\text{cricket}\mid\text{play})=0.7\cdot\tfrac12+0.3\cdot\tfrac2{12}=0.35+0.05=0.4. P(watch∣play)=0.7⋅0+0.3⋅112=0.025P(\text{watch}\mid\text{play})=0.7\cdot0+0.3\cdot\tfrac1{12}=0.025.
      Step 4 — (c). Only the unigram part helps watch: (1−λ)⋅112=0.05(1-\lambda)\cdot\tfrac1{12}=0.05, so 1−λ=0.61-\lambda=0.6 and λ=0.4\lambda=0.4.
      Step 5 — (d). The bigram row adds to 1 and the unigram row adds to 1, so the blend adds to λ⋅1+(1−λ)⋅1=1\lambda\cdot1+(1-\lambda)\cdot1=1.

      answers at a glance: (a) 0.25 and 0.125. (b) 0.4 and 0.025. (c) λ=0.4\lambda=0.4. (d) λ+(1−λ)=1\lambda+(1-\lambda)=1.

      Remember

      Interpolation gives an unseen pair the unigram's share, scaled by 1−λ1-\lambda: more trust in the general adviser, more chance for the unseen.

      Problem 3mediumperplexity, both ways

      (a) A model gave five real next words the probabilities 0.25, 0.5, 0.125, 0.5, 10.25,\ 0.5,\ 0.125,\ 0.5,\ 1. Find the average surprise in bits and the perplexity. (b) What is the perplexity of a model that guesses evenly over 8 words? (c) On a 3-word text a model gave the first two true words 0.5 and 0.25. What must it give the third for the perplexity to be exactly 4? (d) Two models were each scored twice: on their own training text and on new text they had never seen. A scored 45 on its training text and 210 on the new text; B scored 80 and 95. Which would you use, and how many bits per word better is it on the new text?

      What this tests. Perplexity as 2average surprise=(p1⋯pN)−1/N2^{\text{average surprise}}=(p_1\cdots p_N)^{-1/N}, forwards, backwards, and as a judge (Unit 10's overfitting). Plan. Work in bits: log⁡2(1/p)\log_2(1/p) for each word.

      Show the full solution
      Step 1 — (a). Surprises: 2, 1, 3, 1, 0 bits. Average 7/5=1.47/5=1.4 bits. Perplexity 21.4≈2.6392^{1.4}\approx2.639.
      Step 2 — (b). Every word gets 1/81/8: perplexity 8, a fair die with 8 faces.
      Step 3 — (c). (0.5⋅0.25⋅p)−1/3=4(0.5\cdot0.25\cdot p)^{-1/3}=4 means 0.125 p=4−3=1640.125\,p=4^{-3}=\tfrac1{64}, so p=18=0.125p=\tfrac18=0.125. Check: surprises 1, 2, 3; average 2; 22=42^2=4.
      Step 4 — (d). Judge on new text only: B (95 < 210). In bits: log⁡2210≈7.714\log_2 210\approx7.714 and log⁡295≈6.570\log_2 95\approx6.570, so B is log⁡2(210/95)≈1.144\log_2(210/95)\approx1.144 bits per word better. A's big jump from 45 to 210 is the sign of memorising.

      answers at a glance: (a) 1.4 bits; 21.4≈2.6392^{1.4}\approx2.639. (b) 8. (c) p=0.125p=0.125. (d) B; about 1.144 bits per word.

      Remember

      A model that always gives the truth probability pp has perplexity 1/p1/p; and only the score on text the model never saw counts.

      Problem 4easyTF-IDF

      Four documents. D1: the ×4, chai ×3, milk ×1. D2: the ×3, cricket ×2, bat ×1. D3: the ×2, chai ×1, cricket ×1. D4: the ×1, milk ×1, kadak ×2. (a) Give the document frequency and idf=log⁡10(N/df)\text{idf}=\log_{10}(N/\text{df}) of the, chai, milk, cricket, bat and kadak. (b) Give the TF-IDF weights of the, chai and milk in D1. (c) Which word is the best keyword for D4? (d) A new word has idf ≈0.125\approx0.125. In how many of the 4 documents does it appear?

      What this tests. TF-IDF, and reading idf backwards. Plan. Count documents, not copies, for df; then multiply by the counts.

      Show the full solution
      Step 1 — (a). the: in all 4, idf log⁡101=0\log_{10}1=0. chai, milk, cricket: in 2 each, idf log⁡102≈0.301\log_{10}2\approx0.301. bat, kadak: in 1 each, idf log⁡104≈0.602\log_{10}4\approx0.602.
      Step 2 — (b). In D1: the 4×0=04\times0=0, chai 3×0.301≈0.9033\times0.301\approx0.903, milk 1×0.301≈0.3011\times0.301\approx0.301.
      Step 3 — (c). In D4: the 0, milk 1×0.301=0.3011\times0.301=0.301, kadak 2×0.602≈1.2042\times0.602\approx1.204. Kadak is the best keyword.
      Step 4 — (d). log⁡10(4/df)=0.125\log_{10}(4/\text{df})=0.125 gives 4/df≈1.3344/\text{df}\approx1.334, so df=3\text{df}=3 (indeed log⁡10(4/3)≈0.125\log_{10}(4/3)\approx0.125).

      answers at a glance: (a) df 4, 2, 2, 2, 1, 1; idf 0, 0.301, 0.301, 0.301, 0.602, 0.602. (b) 0, 0.903, 0.301. (c) kadak (1.204). (d) 3 documents.

      Remember

      A word everywhere has idf 0; a word in one document out of NN has the biggest idf, log⁡10N\log_{10}N.

      Problem 5mediumPMI

      Counted pairs (N=60N=60): tea meets hot 15, the 12, over 3 times; bat meets hot 3, the 12, over 15 times. (a) Give the row and column totals and the "if strangers" count, row total × column total ÷ NN, for tea with each word. (b) Give PMI⁡(tea,c)\operatorname{PMI}(\text{tea},c) for c = hot, the, over. (c) Give the PPMI of each. (d) Keeping the "if strangers" count for tea–hot fixed, how many tea–hot meetings would make its PMI exactly 1?

      What this tests. PMI as the log of count ÷ chance. Plan. Totals first, then one ratio per box.

      Show the full solution
      Step 1 — (a). Rows: tea 30, bat 30. Columns: hot 18, the 24, over 18. If strangers: tea–hot 30⋅18/60=930\cdot18/60=9, tea–the 30⋅24/60=1230\cdot24/60=12, tea–over 99.
      Step 2 — (b). log⁡2(15/9)=log⁡2(5/3)≈0.737\log_2(15/9)=\log_2(5/3)\approx0.737; log⁡2(12/12)=0\log_2(12/12)=0; log⁡2(3/9)=log⁡2(1/3)≈−1.585\log_2(3/9)=\log_2(1/3)\approx-1.585.
      Step 3 — (c). Keep the positive part: 0.737, 0 and 0.
      Step 4 — (d). PMI 1 means a ratio of 21=22^1=2: 2×9=182\times9=18 meetings.

      answers at a glance: (a) rows 30, 30; columns 18, 24, 18; strangers 9, 12, 9. (b) 0.737, 0, −1.585. (c) 0.737, 0, 0. (d) 18.

      Remember

      PMI counts meetings against chance: 0 means "no more than strangers", and "the" usually scores 0 with everyone.

      Problem 6easycosine of counts

      Count rows over the neighbours (drink, hot, play): tea =(3,4,0)=(3,4,0), coffee =(6,8,0)=(6,8,0), cricket =(0,3,4)=(0,3,4). (a) Compute cos(tea, coffee) and cos(tea, cricket). (b) Compute the straight-line distances tea–coffee and tea–cricket. (c) Which measure clearly says tea is closer to coffee, and why?

      What this tests. Cosine against distance on count rows. Plan. Lengths first: ∥(3,4,0)∥=5\lVert(3,4,0)\rVert=5.

      Show the full solution
      Step 1 — lengths. tea 5, coffee 10, cricket 5.
      Step 2 — (a). tea·coffee =18+32=50=18+32=50, so cos =50/(5⋅10)=1=50/(5\cdot10)=1. tea·cricket =0+12+0=12=0+12+0=12, so cos =12/25=0.48=12/25=0.48.
      Step 3 — (b). tea − coffee =(−3,−4,0)=(-3,-4,0): distance 5. tea − cricket =(3,1,−4)=(3,1,-4): distance 26≈5.099\sqrt{26}\approx5.099.
      Step 4 — (c). The cosine (1 against 0.48). Distance barely prefers coffee (5 against 5.099), because coffee is just "tea, counted twice as often", and distance is fooled by that size.

      answers at a glance: (a) 1 and 0.48. (b) 5 and 26≈5.099\sqrt{26}\approx5.099. (c) the cosine, decisively.

      Remember

      Counts grow with how common a word is; the cosine divides that away.

      Problem 7mediumthe SVD squeeze

      (a) Find the singular values of A=(3113)A=\begin{pmatrix}3&1\\ 1&3\end{pmatrix} and check that σ12+σ22\sigma_1^2+\sigma_2^2 equals the sum of the squares of the entries. (b) A company table has singular values 6, 4, 2, 16,\ 4,\ 2,\ 1. What share of the energy do k=1k=1 and k=2k=2 keep? (c) What is the smallest kk that keeps at least 90%? (d) What is the rank-2 rebuild error?

      What this tests. Energy =∑σi2=\sum\sigma_i^2, and the error of keeping kk. Plan. For a symmetric matrix with positive eigenvalues, the singular values are the eigenvalues.

      Show the full solution
      Step 1 — (a). AA is symmetric; its eigenvalues solve (3−λ)2=1(3-\lambda)^2=1: λ=4,2\lambda=4,2. Both positive, so σ=(4,2)\sigma=(4,2). Check: 16+4=20=9+1+1+916+4=20=9+1+1+9.
      Step 2 — (b). Total 36+16+4+1=5736+16+4+1=57. k=1k=1: 36/57≈63.2%36/57\approx63.2\%. k=2k=2: 52/57≈91.2%52/57\approx91.2\%.
      Step 3 — (c). k=1k=1 is below 90% and k=2k=2 is above, so k=2k=2.
      Step 4 — (d). σ32+σ42=4+1=5≈2.236\sqrt{\sigma_3^2+\sigma_4^2}=\sqrt{4+1}=\sqrt5\approx2.236.

      answers at a glance: (a) σ=(4,2)\sigma=(4,2); 16+4=2016+4=20. (b) 63.2% and 91.2%. (c) k=2k=2. (d) 5≈2.236\sqrt5\approx2.236.

      Remember

      Square the singular values before you add them — energy lives in σ2\sigma^2.

      Problem 8mediumcounting examples

      (a) A 6-word sentence, window C=2C=2: how many examples does CBOW make, and how many pairs does skip-gram make? (b) Find a formula for the number of skip-gram pairs from a sentence of nn words (n≥C+1n\ge C+1). (c) Apply it to n=10n=10, C=3C=3. (d) With C=2C=2, a sentence gave 34 skip-gram pairs. How many words did it have? (e) In a very long text, about how many times more guesses does skip-gram make than CBOW?

      What this tests. The cost difference between the two games, as a general formula. Plan. Count the neighbours of each position, left and right separately.

      Show the full solution
      Step 1 — (a). CBOW: one example per word, 6. Skip-gram: 2+3+4+4+3+2=182+3+4+4+3+2=18.
      Step 2 — (b). The left neighbours add up to 0+1+⋯+C0+1+\dots+C for the first C+1C+1 positions and CC for each of the other n−1−Cn-1-C: 12C(C+1)+C(n−1−C)=Cn−12C(C+1)\tfrac12C(C+1)+C(n-1-C)=Cn-\tfrac12C(C+1). The right side gives the same, so the total is 2Cn−C(C+1)2Cn-C(C+1).
      Step 3 — (c). 2⋅3⋅10−3⋅4=60−12=482\cdot3\cdot10-3\cdot4=60-12=48 pairs (CBOW: 10).
      Step 4 — (d). 4n−6=344n-6=34, so n=10n=10.
      Step 5 — (e). For large nn, (2Cn−C(C+1))/n→2C(2Cn-C(C+1))/n\to2C.

      answers at a glance: (a) 6 and 18. (b) 2Cn−C(C+1)2Cn-C(C+1). (c) 48 (CBOW 10). (d) 10 words. (e) about 2C2C.

      Remember

      Skip-gram makes about 2C2C guesses for every one CBOW makes — that is the whole price of home tuition.

      Problem 9hardone CBOW round

      A vocabulary of four words with d=2d=2. Input vectors: tea (1,0)(1,0), hot (1,1)(1,1), cup (0,1)(0,1), bat (−1,0)(-1,0). Output vectors: tea (1,1)(1,1), hot (0,1)(0,1), cup (1,0)(1,0), bat (−1,−1)(-1,-1). The sentence is "hot tea cup", window 1, and the blank is tea. (a) Find h\mathbf h. (b) Find the four scores and the softmax. (c) Find the loss. (d) Find e=p−y\mathbf e=\mathbf p-\mathbf y and the blame on h\mathbf h, ∑wewuw\sum_w e_w\mathbf u_w. (e) With η=1\eta=1, how far does each context vector move?

      What this tests. The whole CBOW round: average, score, softmax, prediction − truth, and the equal share of the blame. Plan. Keep four decimals; do the output side before the input side.

      Show the full solution
      Step 1 — (a). h=((1,1)+(0,1))/2=(0.5, 1)\mathbf h=\big((1,1)+(0,1)\big)/2=(0.5,\ 1).
      Step 2 — (b). Scores uw⋅h\mathbf u_w\cdot\mathbf h: tea 1.5, hot 1, cup 0.5, bat −1.5. ese^{s}: 4.4817, 2.7183, 1.6487, 0.2231, total 9.0718. Softmax: 0.4940, 0.2996, 0.1817, 0.0246.
      Step 3 — (c). L=−ln⁡0.4940≈0.7052L=-\ln0.4940\approx0.7052.
      Step 4 — (d). e=(−0.5060, 0.2996, 0.1817, 0.0246)\mathbf e=(-0.5060,\ 0.2996,\ 0.1817,\ 0.0246). Blame on h\mathbf h: −0.5060(1,1)+0.2996(0,1)+0.1817(1,0)+0.0246(−1,−1)=(−0.3488, −0.2309)-0.5060(1,1)+0.2996(0,1)+0.1817(1,0)+0.0246(-1,-1)=(-0.3488,\ -0.2309).
      Step 5 — (e). Each of the two context vectors moves by −η⋅12(−0.3488,−0.2309)=(0.1744, 0.1155)-\eta\cdot\tfrac12(-0.3488,-0.2309)=(0.1744,\ 0.1155): toward tea's output vector. (If you also update the output vectors and play the blank again, tea's chance rises to 0.7742.)

      answers at a glance: (a) (0.5,1)(0.5,1). (b) scores 1.5, 1, 0.5, −1.5; softmax 0.4940, 0.2996, 0.1817, 0.0246. (c) 0.7052. (d) e=(−0.5060,0.2996,0.1817,0.0246)\mathbf e=(-0.5060,0.2996,0.1817,0.0246); blame (−0.3488,−0.2309)(-0.3488,-0.2309). (e) (0.1744, 0.1155)(0.1744,\ 0.1155) each.

      Remember

      The committee shares the blame equally: with 2C2C members, each gets 12C\tfrac1{2C} of it.

      Problem 10hardone skip-gram round

      The same four words and vectors as Problem 9. Now tea is the centre word and must guess its two neighbours, hot and cup. (a) Find h\mathbf h and the softmax. (b) Find the loss. (c) Find the summed error E=2p−yhot−ycup\mathbf E=2\mathbf p-\mathbf y_{\text{hot}}-\mathbf y_{\text{cup}} and the blame on the centre word. (d) With η=1\eta=1, what is tea's new input vector? (e) What is the lowest loss skip-gram could ever reach at this position?

      What this tests. One softmax checked against two neighbours, errors that add up, and the floor of 2ln⁡22\ln2. Plan. The centre's own input vector is h\mathbf h — no averaging.

      Show the full solution
      Step 1 — (a). h=vtea=(1,0)\mathbf h=\mathbf v_{\text{tea}}=(1,0). Scores: tea 1, hot 0, cup 1, bat −1. Softmax: 0.3995, 0.1470, 0.3995, 0.0541.
      Step 2 — (b). L=−ln⁡0.1470−ln⁡0.3995≈1.9176+0.9176=2.8352L=-\ln0.1470-\ln0.3995\approx1.9176+0.9176=2.8352.
      Step 3 — (c). E=(0.7990, −0.7061, −0.2010, 0.1081)\mathbf E=(0.7990,\ -0.7061,\ -0.2010,\ 0.1081). Blame on the centre: 0.7990(1,1)−0.7061(0,1)−0.2010(1,0)+0.1081(−1,−1)=(0.4898, −0.0152)0.7990(1,1)-0.7061(0,1)-0.2010(1,0)+0.1081(-1,-1)=(0.4898,\ -0.0152).
      Step 4 — (d). vtea←(1,0)−(0.4898,−0.0152)=(0.5102, 0.0152)\mathbf v_{\text{tea}}\leftarrow(1,0)-(0.4898,-0.0152)=(0.5102,\ 0.0152). The whole blame goes to the centre word.
      Step 5 — (e). One list must share its chances between hot and cup: the best is 0.5 each, a loss of 2ln⁡2≈1.3862\ln2\approx1.386.

      answers at a glance: (a) (1,0)(1,0); 0.3995, 0.1470, 0.3995, 0.0541. (b) 2.8352. (c) E=(0.7990,−0.7061,−0.2010,0.1081)\mathbf E=(0.7990,-0.7061,-0.2010,0.1081); blame (0.4898,−0.0152)(0.4898,-0.0152). (d) (0.5102, 0.0152)(0.5102,\ 0.0152). (e) 2ln⁡2≈1.3862\ln2\approx1.386.

      Remember

      Skip-gram's centre word takes the full sum of its neighbours' errors — nothing is divided.

      Problem 11hardone negative-sampling step

      v=(0,1)\mathbf v=(0,1), real neighbour u+=(1,1)\mathbf u_+=(1,1), one negative u−=(1,−1)\mathbf u_-=(1,-1), step size η=0.5\eta=0.5. (a) Find g+=1−σ(u+⋅v)g_+=1-\sigma(\mathbf u_+\cdot\mathbf v) and g−=σ(u−⋅v)g_-=\sigma(\mathbf u_-\cdot\mathbf v). (b) Do one step of the pull-and-push rules for all three vectors. (c) Give the new scores u±⋅v\mathbf u_\pm\cdot\mathbf v and the loss before and after.

      What this tests. The rules u++=ηg+v\mathbf u_+\mathrel{+}=\eta g_+\mathbf v, u−−=ηg−v\mathbf u_-\mathrel{-}=\eta g_-\mathbf v, v+=η(g+u+−g−u−)\mathbf v\mathrel{+}=\eta(g_+\mathbf u_+-g_-\mathbf u_-), all using the OLD vectors. Plan. Compute the two "how wrong" numbers once, then update.

      Show the full solution
      Step 1 — (a). u+⋅v=1\mathbf u_+\cdot\mathbf v=1: g+=1−σ(1)≈0.2689g_+=1-\sigma(1)\approx0.2689. u−⋅v=−1\mathbf u_-\cdot\mathbf v=-1: g−=σ(−1)≈0.2689g_-=\sigma(-1)\approx0.2689.
      Step 2 — the neighbours. u+←(1,1)+0.5(0.2689)(0,1)=(1, 1.1345)\mathbf u_+\leftarrow(1,1)+0.5(0.2689)(0,1)=(1,\ 1.1345). u−←(1,−1)−0.5(0.2689)(0,1)=(1, −1.1345)\mathbf u_-\leftarrow(1,-1)-0.5(0.2689)(0,1)=(1,\ -1.1345).
      Step 3 — the centre word. g+u+−g−u−=0.2689((1,1)−(1,−1))=(0, 0.5379)g_+\mathbf u_+-g_-\mathbf u_-=0.2689\big((1,1)-(1,-1)\big)=(0,\ 0.5379), so v←(0,1)+0.5(0,0.5379)=(0, 1.2689)\mathbf v\leftarrow(0,1)+0.5(0,0.5379)=(0,\ 1.2689).
      Step 4 — (c). New scores: 1.1345×1.2689≈1.43961.1345\times1.2689\approx1.4396 and −1.4396-1.4396. Loss before: −2ln⁡σ(1)≈0.6265-2\ln\sigma(1)\approx0.6265. After: −2ln⁡σ(1.4396)≈0.4254-2\ln\sigma(1.4396)\approx0.4254.

      answers at a glance: (a) g+=g−≈0.2689g_+=g_-\approx0.2689. (b) u+=(1,1.1345)\mathbf u_+=(1,1.1345), u−=(1,−1.1345)\mathbf u_-=(1,-1.1345), v=(0,1.2689)\mathbf v=(0,1.2689). (c) scores ±1.4396\pm1.4396; loss 0.6265 → 0.4254.

      Remember

      Use the old vectors on the right-hand side of all three updates — compute first, then overwrite.

      Problem 12mediumdown the tree

      A hierarchical softmax with four leaves (LL, LR, RL, RR) and h=(2,−1)\mathbf h=(2,-1). The root has θ=(1,1)\boldsymbol\theta=(1,1), the left fork (0,1)(0,1), the right fork (0.5,1)(0.5,1); each fork sends σ(θ⋅h)\sigma(\boldsymbol\theta\cdot\mathbf h) to the left. (a) Find the three fork scores θ⋅h\boldsymbol\theta\cdot\mathbf h. (b) Find the chance of each leaf. (c) Check that they add up to 1. (d) A balanced tree over 30 000 words: how many decisions per guess, and how many times less work than a full softmax?

      What this tests. A leaf's chance as the product of its left/right decisions, and the log⁡2V\log_2V cost. Plan. Remember σ(−z)=1−σ(z)\sigma(-z)=1-\sigma(z).

      Show the full solution
      Step 1 — (a). Root: 2−1=12-1=1. Left fork: 0⋅2+1⋅(−1)=−10\cdot2+1\cdot(-1)=-1. Right fork: 1−1=01-1=0.
      Step 2 — (b). Root left σ(1)=0.7311\sigma(1)=0.7311, right 0.2689. LL =0.7311⋅σ(−1)=0.7311⋅0.2689≈0.1966=0.7311\cdot\sigma(-1)=0.7311\cdot0.2689\approx0.1966. LR =0.7311⋅0.7311≈0.5344=0.7311\cdot0.7311\approx0.5344. RL =0.2689⋅σ(0)=0.1345=0.2689\cdot\sigma(0)=0.1345. RR =0.2689⋅0.5=0.1345=0.2689\cdot0.5=0.1345.
      Step 3 — (c). 0.1966+0.5344+0.1345+0.1345=10.1966+0.5344+0.1345+0.1345=1 (exactly, before rounding).
      Step 4 — (d). 214=16 384<30 000≤215=32 7682^{14}=16\,384<30\,000\le2^{15}=32\,768, so 15 decisions; 30 000/15=2 00030\,000/15=2\,000 times less work.

      answers at a glance: (a) 1, −1, 0. (b) 0.1966, 0.5344, 0.1345, 0.1345. (c) 1. (d) 15 decisions; 2 000 times less.

      Remember

      Every fork splits what it receives into two parts that add up, so the leaves always add up to 1.

      Problem 13mediumsubsampling

      Subsampling keeps each copy of a word with frequency ff with chance t/f\sqrt{t/f} (and always if f≤tf\le t), with t=10−5t=10^{-5}. (a) Give the keep chances for f=10−3f=10^{-3}, f=4×10−4f=4\times10^{-4} and f=2.5×10−6f=2.5\times10^{-6}. (b) Of 1 000 copies of the 10−310^{-3} word, how many are kept on average? (c) In another model a word with f=0.01f=0.01 is kept 5% of the time. What tt was used? (d) A word with f1=10−3f_1=10^{-3} is 100 times as common as one with f2=10−5f_2=10^{-5}. How many times as common is it after subsampling?

      What this tests. The keep rule forwards and backwards, and the square-root flattening. Plan. A kept share is ft/f=tff\sqrt{t/f}=\sqrt{tf}.

      Show the full solution
      Step 1 — (a). 10−5/10−3=0.01=0.1\sqrt{10^{-5}/10^{-3}}=\sqrt{0.01}=0.1. 10−5/(4×10−4)=0.025≈0.158\sqrt{10^{-5}/(4\times10^{-4})}=\sqrt{0.025}\approx0.158. 2.5×10−6≤t2.5\times10^{-6}\le t: always kept, 1.
      Step 2 — (b). 1000×0.1=1001000\times0.1=100.
      Step 3 — (c). t/0.01=0.05\sqrt{t/0.01}=0.05 gives t/0.01=0.0025t/0.01=0.0025, so t=2.5×10−5t=2.5\times10^{-5}.
      Step 4 — (d). Kept shares: tf1=10−8=10−4\sqrt{t f_1}=\sqrt{10^{-8}}=10^{-4}; the second word has f2=tf_2=t, so it keeps all of its 10−510^{-5}. The ratio is 10−4/10−5=1010^{-4}/10^{-5}=10 — down from 100.

      answers at a glance: (a) 0.1, about 0.158, 1. (b) 100. (c) t=2.5×10−5t=2.5\times10^{-5}. (d) 10 times.

      Remember

      Subsampling turns a word's share ff into about tf\sqrt{tf}: common words shrink the most, rare words are untouched.

      Problem 14mediumGloVe ratios

      Around "ice" and around "steam", 1 000 context words were counted each. The probe solid appears 38 and 2 times, gas 1 and 19, water 60 and 60, fashion 2 and 2. (a) Give P(k∣ice)/P(k∣steam)P(k\mid\text{ice})/P(k\mid\text{steam}) for each probe. (b) Give the natural log of each ratio — what GloVe wants (wice−wsteam)⋅w~k(\mathbf w_{\text{ice}}-\mathbf w_{\text{steam}})\cdot\tilde{\mathbf w}_k to be. (c) Which probe vectors should end up at right angles to wice−wsteam\mathbf w_{\text{ice}}-\mathbf w_{\text{steam}}? (d) Give GloVe's weights f(x)=(x/100)3/4f(x)=(x/100)^{3/4} (1 above 100) for x=38x=38, 2, 60 and 150.

      What this tests. Meaning in ratios, and why rare counts get small weights. Plan. Both targets have 1 000 contexts, so the ratio of probabilities is the ratio of counts.

      Show the full solution
      Step 1 — (a). solid 38/2=1938/2=19, gas 1/19≈0.05261/19\approx0.0526, water 60/60=160/60=1, fashion 2/2=12/2=1.
      Step 2 — (b). ln⁡19≈2.944\ln19\approx2.944, ln⁡(1/19)≈−2.944\ln(1/19)\approx-2.944, ln⁡1=0\ln1=0, ln⁡1=0\ln1=0.
      Step 3 — (c). Water and fashion: their target dot product is 0. Water is shared by both, fashion by neither — either way it cannot tell ice from steam.
      Step 4 — (d). 0.380.75≈0.4840.38^{0.75}\approx0.484, 0.020.75≈0.05320.02^{0.75}\approx0.0532, 0.60.75≈0.6820.6^{0.75}\approx0.682, and 1 for 150.

      answers at a glance: (a) 19, 0.0526, 1, 1. (b) 2.944, −2.944, 0, 0. (c) water and fashion. (d) 0.484, 0.0532, 0.682, 1.

      Remember

      A probe that tells two words apart gives a ratio far from 1; one that doesn't gives 1, and its arrow is at right angles to their difference.

      Problem 15hardBPE by hand

      A corpus: low ×5, lower ×2, newest ×6, widest ×3. Run byte-pair encoding from single letters; when two pairs tie, merge the one met first reading the corpus in order. (a) Count the neighbouring pairs and find the first merge. (b) Find the next three merges. (c) Cut "lowest" and "slow" with these four merges. (d) How many symbols does the whole corpus have (counting repeats) before any merge, and after the four merges?

      What this tests. The BPE loop — count, merge the most frequent pair, repeat — and the tie rule. Plan. Multiply every pair by its word's count; recount after each merge.

      Show the full solution
      Step 1 — (a). e+s: 6 (newest) + 3 (widest) = 9; s+t: 9 as well; w+e: 2 + 6 = 8; l+o and o+w: 7 each; n+e, e+w: 6; w+i, i+d, d+e: 3; e+r: 2. The top two tie at 9, and e+s is met first (in "newest"), so merge 1 is e+s → es (9).
      Step 2 — (b). Now es+t = 9 is alone at the top: merge 2 es+t → est (9). Then l+o and o+w tie at 7, and l+o comes first: merge 3 l+o → lo (7). Then lo+w = 7: merge 4 lo+w → low (7).
      Step 3 — (c). "lowest": l o w e s t → (es) → (est) → (lo) → (low): low · est. "slow": s l o w → s · low.
      Step 4 — (d). Before: 3⋅5+5⋅2+6⋅6+6⋅3=793\cdot5+5\cdot2+6\cdot6+6\cdot3=79 letters. After: low (1 symbol) ×5, low e r (3) ×2, n e w est (4) ×6, w i d est (4) ×3: 5+6+24+12=475+6+24+12=47.

      answers at a glance: (a) e+s (9, tie with s+t broken by order). (b) es+t (9), l+o (7), lo+w (7). (c) low · est; s · low. (d) 79 → 47.

      Remember

      BPE turns frequent chunks into single tokens and spells everything else from pieces — so the text gets shorter and no word is ever unknown.

      Problem 16mediumanalogy

      Toy vectors: India =(1,0,3)=(1,0,3), Delhi =(1,1.2,3)=(1,1.2,3), Japan =(3,0,1)=(3,0,1), Tokyo =(3,1,1)=(3,1,1), Kyoto =(3,1,2)=(3,1,2). (a) Compute q=\mathbf q= Delhi − India + Japan. (b) Compute the cosine of q\mathbf q with Tokyo, Kyoto, Japan and Delhi. (c) Which word does the search return (skipping the inputs)? (d) Would the answer change if the inputs were allowed?

      What this tests. Analogy arithmetic and the cosine search. Plan. Add first, then one cosine per candidate.

      Show the full solution
      Step 1 — (a). q=(1−1+3, 1.2−0+0, 3−3+1)=(3, 1.2, 1)\mathbf q=(1-1+3,\ 1.2-0+0,\ 3-3+1)=(3,\ 1.2,\ 1); ∥q∥=11.44≈3.382\lVert\mathbf q\rVert=\sqrt{11.44}\approx3.382.
      Step 2 — (b). Tokyo: 11.2/(3.382⋅11)≈0.998411.2/(3.382\cdot\sqrt{11})\approx0.9984. Kyoto: 12.2/(3.382⋅14)≈0.964012.2/(3.382\cdot\sqrt{14})\approx0.9640. Japan: 10/(3.382⋅10)≈0.934910/(3.382\cdot\sqrt{10})\approx0.9349. Delhi: 7.44/(3.382⋅11.44)≈0.65037.44/(3.382\cdot\sqrt{11.44})\approx0.6503.
      Step 3 — (c). Tokyo, with 0.9984.
      Step 4 — (d). No: the inputs Japan (0.9349) and Delhi (0.6503) score below Tokyo here. (In real trained vectors they often would not.)

      answers at a glance: (a) (3,1.2,1)(3,1.2,1). (b) 0.9984, 0.9640, 0.9349, 0.6503. (c) Tokyo. (d) no.

      Remember

      The answer to A−B+CA-B+C is a point, not a word; the nearest word by cosine is the answer.

      Next up

      Unit 17 · Machines with Memory →

      Every model in this unit looked at a fixed window of words. Next, a network reads a sentence one word at a time and carries a running memory along — the same layer used again and again. Then we follow the blame backwards through time and find out why memory fades or explodes, and how gates fix it.

      ← Unit 15 · The Network, Whole · All units