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:
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?
- Weigh the money sense0.8 × (0.9, 0.1) = (0.72, 0.08)
Each number of the money vector, times its share.
- Weigh the river sense0.2 × (0.1, 0.9) = (0.02, 0.18)
The rare sense gets a fifth of the say.
- 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.
- 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?
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?
- 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.
- Add them(0.37 + 0.05, 0.13 + 0.45) = (0.42, 0.58)
The new vector sits between bank's row and river.
- 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.
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?
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?
- 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.
- 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.
- 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.
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?
Where you'll meet it
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.
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.
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?
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?
3
Softmax gets the scores (3.0, 3.0, 3.0). What weights come out?
What to remember
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).
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).
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
- A static row blends every sense of a word
- The common sense counts most: bank = (0.74, 0.26)
- 0.5 × bank + 0.5 × river = (0.42, 0.58)
- The same word gets a new vector in each sentence
- Equal weights blur the useful word
- Each word needs its own weight
- e to each score, divided by the total
- Positive weights that add up to 1
- 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.
Read next
- Linear Algebraic Structure of Word Senses, with Applications to PolysemyArora and colleagues, 2016Shows that a static vector holds a word's senses as a weighted sum, and how to pull them apart again.
- Deep contextualized word representationsPeters and colleagues, 2018ELMo, an early model that gave each use of a word its own vector.
- How Contextual are Contextualized Word Representations?Kawin Ethayarajh, 2019Measures how much a word's vector changes from sentence to sentence in ELMo, BERT and GPT-2.
Transformers overviewSpotted a mistake? Tell us.