insideout Get Pro

01 · Context changes meaning

Free

Transformers, lesson 1

Context changes meaning

One fixed vector per word can't follow what a word means in context.

A language model reads every word as a vector, and the vector for "bank" has to mean money in one sentence and a river's edge in the next. This lesson shows why one fixed vector can't do that, and the move that fixes it, called attention. You need the dot product and cosine from Tokens and Embeddings, and softmax from Neural Networks.

By the end, you can:

  1. Work out where a word's one vector lands when the word has two meanings.
  2. Build a vector for one use of a word by mixing in a neighbour.
  3. Turn scores into weights with softmax, and mix the vectors with them.

Part 1. One vector for every meaning

Work out where a word's one vector lands when the word has two meanings.

Plenty of common words do more than one job. "bank" is a place for money or the edge of a river. "light" means not heavy, or not dark. A static embedding still gives each word one row in its table, so every job the word does has to share that row.

Example 1.1

Where "bank" lands

Give every word two made-up numbers: how money-ish it is, and how river-ish. Money is (0.9, 0.1) and river is (0.1, 0.9). Training text uses "bank" in the money sense 80% of the time. Say its row is a blend of the two senses, weighted by those shares. Where does it land?

  1. Weigh the money sense0.8 × (0.9, 0.1) = (0.72, 0.08)

    Each number of the money vector, times its share.

  2. Weigh the river sense0.2 × (0.1, 0.9) = (0.02, 0.18)

    The rare sense gets a fifth of the say.

  3. Add the two(0.72 + 0.02, 0.08 + 0.18) = (0.74, 0.26)

    Bank's row sits a fifth of the way from money towards river.

  4. Compare with cosinecos(bank, money) = 0.97, cos(bank, river) = 0.43

    A cosine near 1 means the same direction. Bank points almost exactly at money.

Answer(0.74, 0.26): nearly a money word.

Why a blend? Training nudges bank's row towards the words around it, every time bank appears. Money sentences turn up four times as often, so they pull four times as often. Arora and colleagues showed that, under their model of text, a word's row is close to its sense vectors weighted by those shares.

Word sense

One meaning of a word: bank as a place for money, bank as a river's edge. A static embedding has one row per word, so it holds a blend of the word's senses, weighted by how often each one appears.

bank = 0.8 × money + 0.2 × river

The common sense wins the blend, so the row works well enough for it. The rare sense loses. Every time bank means a river's edge, the model starts from a vector that points at money, with a cosine of only 0.43 to river.

Your turn

Another word appears 60% of the time in the money sense and 40% in the river sense. With money at (0.9, 0.1) and river at (0.1, 0.9), where does its row land?

0.6 × (0.9, 0.1) + 0.4 × (0.1, 0.9) = (0.54 + 0.04, 0.06 + 0.36) = (0.58, 0.42). (0.42, 0.58) gives each sense the other's share, (0.5, 0.5) ignores how often each sense appears, and (1.0, 1.0) adds the vectors without weighing them.

Part 2. Mix in the neighbours

Build a vector for one use of a word by mixing in a neighbour.

You can tell which bank someone means from the other words in the sentence. "We sat on the river bank" has river in it. So let the model do what you do: build a fresh vector for this one use of bank, by mixing a neighbour's vector into it.

Example 2.1

Bank, next to river

In "we sat on the river bank", mix bank's row (0.74, 0.26) half and half with river (0.1, 0.9). Where does the new vector point?

  1. Take half of each0.5 × (0.74, 0.26) + 0.5 × (0.1, 0.9)

    Two weights, 0.5 and 0.5, that add up to 1.

  2. Add them(0.37 + 0.05, 0.13 + 0.45) = (0.42, 0.58)

    The new vector sits between bank's row and river.

  3. Compare with cosinecos(new, money) = 0.67, cos(new, river) = 0.87

    It now leans towards river. The table row had only 0.43.

Answer(0.42, 0.58), a bank that leans towards river.

money-ishriver-ish00.50.511money(0.9, 0.1)river(0.1, 0.9)bank's row(0.74, 0.26)bank, here(0.42, 0.58)cosine with river0.43 → 0.87
Figure 1Every blend of money and river sits on the dotted line. Bank's table row is near money. Mixed half and half with river, the bank in this sentence moves past the middle, towards river.

Weights that add up to 1 keep the new vector on the line between the two you mix. In a money sentence, bank would be mixed with a word like cash and lean the other way. Same word, same table row, two different vectors.

Contextual embedding

A vector for one use of a word, built from the word and the words around it. A static embedding gives one vector per word. A contextual embedding gives one per use, so the same word gets a new vector in every sentence.

bank here = 0.5 × bank + 0.5 × river

The trap is mixing in every neighbour equally. In "I sat on the bank of the river", bank has seven neighbours. Give them equal shares and river gets a seventh of the say, while "the", "on" and "of" add blur. Each neighbour needs its own weight.

Your turn

Mix bank's row (0.74, 0.26) with river (0.1, 0.9), giving bank 0.25 of the say and river 0.75. What vector comes out?

0.25 × (0.74, 0.26) + 0.75 × (0.1, 0.9) = (0.185 + 0.075, 0.065 + 0.675) = (0.26, 0.74). (0.58, 0.42) swaps the two weights, (0.84, 1.16) adds the vectors without weighing them, and (0.42, 0.58) is the half-and-half mix.

Part 3. Weights from scores

Turn scores into weights with softmax, and mix the vectors with them.

Say the model can give each word in "the river bank", bank included, a score for how useful it is to bank. Scores can be any size, but weights for a mix must be positive and add up to 1. Softmax, from Neural Networks, makes that turn.

Example 3.1

Bank in "the river bank"

Bank scores the three words: "the" 0.1, river 2.0, bank itself 1.0. Their vectors are "the" (0.5, 0.5), river (0.1, 0.9) and bank (0.74, 0.26). What new vector does bank get?

  1. Raise e to each scoree^0.1 = 1.105, e^2.0 = 7.389, e^1.0 = 2.718

    e is about 2.718. Every result is positive, and a bigger score grows much faster.

  2. Divide by the total1.105 + 7.389 + 2.718 = 11.212

    That gives the weights 0.10, 0.66 and 0.24. They add up to 1, and river gets two thirds of the say.

  3. Mix the vectors(0.05 + 0.066 + 0.178, 0.05 + 0.594 + 0.062) = (0.29, 0.71)

    Each vector times its weight: "the" gives (0.05, 0.05), river (0.066, 0.594) and bank (0.178, 0.062). Mostly river.

Answer(0.29, 0.71), with a cosine of 0.96 to river.

wordscoree^scoreweightthe0.11.1050.10river2.07.3890.66bank1.02.7180.2411.212totaleach ÷ 11.212new bankweights × vectors, added up(0.29, 0.71)
Figure 2Bank scores every word in the phrase, itself included. Softmax turns the scores into weights, and the weights mix the vectors. The useful word, river, gets two thirds of the say.

Raising e to a score makes every weight positive, even for a negative score, and dividing by the total makes the weights add up to 1. The biggest score always gets the biggest weight. Only the gaps between scores matter, so adding 5 to every score changes nothing.

Softmax and attention

Softmax turns scores into weights: raise e to each score, then divide by the total. Attention is the whole move: score the words, softmax the scores, then mix the words' vectors with the weights. A transformer does it for every word at once.

weight = e^score ÷ (total of e^score)

Equal scores give equal weights, which brings back the blur from part 2. Attention only helps when the scores pick out the useful words, and here they were made up. The next lesson shows where real scores come from.

Your turn

Bank gives three words the scores 3.0, 1.0 and 1.0. What weights does softmax give them?

e^3 = 20.09 and e^1 = 2.718, so the total is 25.52. Then 20.09 ÷ 25.52 = 0.79 and 2.718 ÷ 25.52 = 0.11 (rounded). (0.60, 0.20, 0.20) divides the scores by their total and skips e. Softmax never gives a word exactly 0.

Where you'll meet it

In interviews

A common warm-up: why can't word2vec tell the two banks apart, and what does a transformer do instead? Answer in two moves. A static table has one row per word, so it stores a blend of every sense. A transformer starts from that row and mixes in the other words with attention weights, so each use ends with its own vector.

On the job

In Hugging Face transformers, BERT keeps its static table at model.embeddings.word_embeddings, and bank's row there is the same in every sentence. The vectors in last_hidden_state differ, because every layer mixes in the other words. Ethayarajh (2019) found that in ELMo, BERT and GPT-2, a static vector explains under 5% of how a word's contextual vectors vary, on average.

Score, softmax, mix, in NumPy
import numpy as np

vecs = np.array([[0.5, 0.5], [0.1, 0.9], [0.74, 0.26]])   # the, river, bank
scores = np.array([0.1, 2.0, 1.0])     # how useful each word is to bank

weights = np.exp(scores) / np.exp(scores).sum()
print(weights.round(2))                # [0.1  0.66 0.24]
print((weights @ vecs).round(2))       # [0.29 0.71]

equal = np.exp([1.0, 1.0, 1.0]) / np.exp([1.0, 1.0, 1.0]).sum()
print((equal @ vecs).round(2))         # [0.45 0.55]

weights @ vecs is the mix in one step: each vector times its weight, added up. With equal scores you get the plain average, and river's pull drops from 0.71 to 0.55.

Check yourself

Three questions from across the lesson. Try each one before you look back.

1

Which meaning of a word suffers most from having one fixed vector?

The common sense dominates the blend, so the vector serves it well enough. The rare senses barely move the vector at all. Every time "bank" means a riverside, the model starts from a vector pointing at money.

2

BERT reads "we sat on the river bank" and "I paid cash at the bank". Which of its vectors for bank is the same in both sentences?

The table is a lookup, so bank's row is identical in both. Every layer after it mixes in the other words, so the last-layer vectors differ: one leans towards river, the other towards money.

3

Softmax gets the scores (3.0, 3.0, 3.0). What weights come out?

e^3 is about 20.1 each time, and each one is a third of the total. Equal scores give equal weights. Only the gaps between scores matter: (3, 3, 3) and (0, 0, 0) give the same weights.

What to remember

  1. 1One vector for every meaning

    A static embedding has one row per word, a blend of its senses weighted by how often each appears: 0.8 × money + 0.2 × river = (0.74, 0.26).

  2. 2Mix in the neighbours

    A contextual embedding mixes in the neighbours, so the same word gets a new vector in each sentence: 0.5 × bank + 0.5 × river = (0.42, 0.58).

  3. 3Weights from scores

    Attention scores the words, turns the scores into weights with softmax and mixes the vectors: scores (0.1, 2.0, 1.0) give weights (0.10, 0.66, 0.24).

Recap and going further

The lesson on one page

One row, many senses
  • A static row blends every sense of a word
  • The common sense counts most: bank = (0.74, 0.26)
Mix in the neighbours
  • 0.5 × bank + 0.5 × river = (0.42, 0.58)
  • The same word gets a new vector in each sentence
Not every neighbour counts
  • Equal weights blur the useful word
  • Each word needs its own weight
A vector for each use, not each word
Softmax
  • e to each score, divided by the total
  • Positive weights that add up to 1
Attention
  • Score, softmax, mix
  • For every word in the sentence at once

Try this

Watch "bank" change with its sentence

Load bert-base-uncased with Hugging Face transformers. Write five sentences that use "bank": three about money and two about rivers. Run each with output_hidden_states=True, take the vector at the bank position from every layer, and compare the sentences pair by pair with cosine. Bank's row in the token table (model.embeddings.word_embeddings) is the same in all five, so every difference you find was made by the layers.

You need: Python with PyTorch and pip install transformers. The model downloads once, about 440 MB, and runs on a laptop.

Look for

  • Last-layer cosines between two money sentences, and between a money sentence and a river one.
  • The first layer where the two meanings clearly pull apart.
  • Where a sentence with no clue words, such as "we met at the bank", lands between the two groups.

The words, in plain language

Word sense
One meaning of a word: bank as a place for money, bank as a river's edge. A static embedding has one row per word, so it holds a blend of the word's senses, weighted by how often each one appears.
Contextual embedding
A vector for one use of a word, built from the word and the words around it. A static embedding gives one vector per word. A contextual embedding gives one per use, so the same word gets a new vector in every sentence.
Softmax and attention
Softmax turns scores into weights: raise e to each score, then divide by the total. Attention is the whole move: score the words, softmax the scores, then mix the words' vectors with the weights. A transformer does it for every word at once.

Transformers overviewSpotted a mistake? Tell us.