What a Token Is
We can read the word cat, but a numerical model needs a representation it can process. A tokenizer divides text into pieces and maps those pieces to IDs, giving us a starting point for working with language.
14 sections · 14 questions · 4 coding challenges
The arrow keys move between sections too.
How Did Text Become Something a Program Could Work With?
BOTIE
Tools such as Lesk and Schmidt's Lex, documented in 1975, let programmers describe patterns and turn matching character sequences into items for later processing. This is part of the computing history of tokens. Natural-language tokenizers inherited the need to define units, although their rules and goals differ from those of a programming-language lexer.
For a language model, we also associate each recognised piece with an ID. A piece such as cat can have a particular table entry, and the model can use that entry consistently. The ID gives the piece an address; it does not supply its meaning. Our next question is therefore which pieces to recognise, because choosing words, word parts, characters, or bytes creates different practical problems.
Sources for this history
How Can Our Models Read Language?
As humans, we can read the letters and words in a sentence. A numerical model needs a representation it can process. We first need to decide which pieces of the text it will receive and how to identify each piece.
A token is one of those pieces. Its ID names the piece; the ID does not supply its meaning.
Begin with readable text
Keep a short sentence in view. We understand its words, but the next processing stage needs explicitly identified units. Nothing about a raw character sequence says which units a particular tokenizer should choose.
Text
- the cat sat
Piece selection and numbering are separate decisions
We can now inspect a vocabulary and follow encoding and decoding on a sentence with punctuation and word parts.
Later lessons explain why smaller pieces help with unfamiliar words and what different boundary rules preserve.
Explore the full example
Compare the text pieces with their IDs, then inspect the decoded text. An exact round trip depends on which information the scheme retained.
…
Part 1. Writing Is Not Numbers
1. One sentence, and what a model can do with it
We will use one sentence throughout this page and revisit it in the later tokenization lessons. It contains several useful boundary cases while remaining short enough to inspect.
Dr. Alvarez didn't expect the low-cost re-analysis.The full stop after Dr. belongs to an abbreviation. The apostrophe is part of a contraction. A hyphen joins low-cost, and re- appears at the start of re-analysis. A splitting rule must decide how to handle each case. We will begin with spaces alone so those decisions are easy to see.
The numerical layers on this site need numbers in place of those text pieces. The tokenizer supplies the IDs, and an embedding layer can then look up trainable vectors. If re-analysis. and re-analysis are two separate vocabulary entries, as the scheme in Part 3 makes them, they start with separate identities. A model can still learn a relationship between their vectors from context, but the token IDs do not provide that relationship themselves.
Keep in mind
2. A piece of text with a number beside it
A token is one piece produced by the chosen scheme. For inspection, the SDK keeps that piece beside its ID. The encoding records these tokens in the order they occur, so a reader can check which text each ID represents.
token = ( a piece of text , a whole number )
encoding = the tokens one text became, in orderCutting the running sentence at every space gives seven pieces, and against the table Part 2 builds those seven pieces carry the numbers 3, 2, 14, 19, 43, 28 and 32. A model sees only that second list. Everything it will ever know about the sentence has to arrive through those seven numbers and through the order they came in.
Seven pieces, seven numbers
Dr. 3
Alvarez 2
didn't 14
expect 19
the 43
low-cost 28
re-analysis. 32Notice that the full stop stayed attached to the last piece and that the contraction was left whole. Both of those are consequences of cutting at spaces and nowhere else, and both will be argued with later in the section.
Keep in mind
3. The number says which piece, and nothing else
It is tempting to read those seven numbers as measurements, since every other number on this site is one. They are not. A token number is a position in a list, and the only question it answers is which entry of the list this piece is. Nothing follows from one number being larger than another, and nothing follows from two numbers being close.
The list this page builds is in alphabetical order, so neighbouring numbers hold pieces that happen to share a first letter. That produces both kinds of accident at once. The pieces at 29 and 30 are not and notes, which share three letters and nothing else, and they are as close as two numbers can be. The word The is at 6 and the word the is at 43, the same word with one letter capitalised, at a different position in the vocabulary.
›Why the ordering can be anything at all
Any one-to-one assignment of numbers to pieces works equally well, because the model looks each number up in a table of learned rows and reads the row, so the number is only an address. Shuffle the numbers and shuffle the rows with them and the model is unchanged. What must not change is the assignment itself, once anything has been trained against it, since the rows were learned in the order the numbers named and rearranging one without the other points every piece at somebody else’s row.
Keep in mind
Part 2. What a Vocabulary Promises
4. A list, and the position each piece holds
A vocabulary is a list of pieces, fixed once it is built, with each piece owning its position in the list. Position zero is the first entry, position one the second, and the number a piece goes in as is simply where it sits. There is no second table of numbers to keep in step with the first, which is the whole reason for making the position the number rather than storing a number beside each piece.
The tables on this page are built from six sentences, the running sentence and five more from the same notebook, which is small enough that the whole list fits on a screen and is worth reading through in the playground above. Cutting those six sentences at spaces gives 47 distinct pieces, and the table holds 48 entries, the extra one being the reserved entry Part 4 is about. Cutting them into single characters gives 37 distinct pieces and a table of 38.
| cut into | distinct pieces | entries in the table |
|---|---|---|
| single characters | 37 | 38 |
| whole words | 47 | 48 |
Both counts are over the same six sentences, so the only thing that differs is what counts as a piece.
Keep in mind
5. The same piece gets the same number every time
The first promise is the one that makes learning possible at all. Whenever the same piece appears, in whatever sentence and in whatever position, the same number comes out. If that were not so, a model that had learned something about a word in one sentence would have learned nothing about the same word in the next, and every occurrence would be a fresh start.
Encoding the running sentence and a second sentence from the same six shows it. The word the is the fifth piece of the first and the tenth piece of the second, and it carries the number 43 in both.
Dr. Alvarez didn't expect the low-cost re-analysis.
3 2 14 19 43 28 32
The drift was small, though it was larger than the effect she expected.
6 15 47 40 44 26 47 27 42 43 17 39 20The second line also shows the promise being kept in a way that will annoy a reader. The word was appears twice in that sentence and is 47 both times, which is the promise working. But The at the front is 6 while the further along is 43, and expect at 19 and expected. at 20 are two unrelated entries as far as the table is concerned. The promise is about pieces being identical as strings, and it says nothing about their being the same word.
Keep in mind
6. The numbers turn back into text
The second promise runs the other way. Given a run of numbers, each one is looked up by position and the pieces are glued back together, so a person can read what a model was shown and a model that produces numbers can have its output read. Both matter. Without it a generated sequence would be a list of integers nobody could evaluate.
encode text → numbers
decode numbers → textDecoding is the shorter half, since it has nothing to decide. Look each number up, refuse any number no entry owns, glue. What varies between schemes is only the glue, and for the whole-word scheme here the glue is a single space, which turns out in Part 5 to be the thing that stops the round trip being exact. Running both halves on the running sentence gives back the sentence character for character, under both cutting rules.
Keep in mind
7. What the size of the table costs
The number of entries is not free, because a model gives every entry a row of its own. Whatever a model learns about a piece lives in that row, the rows are learned from the text, and a row belonging to a piece that turns up twice in the training text is learned from two occurrences.
Take a row of 768 numbers, which is an ordinary width. The whole-word table here has 48 entries and the character table has 38, and each entry needs one such row, so the count of numbers a model has to learn is the count of entries multiplied by the width of a row.
whole words 48 × 768 = 36,864 numbers
single characters 38 × 768 = 29,184 numbers
36,864 / 29,184 ≈ 1.26The whole-word table asks for about a quarter more numbers than the character table, and none of them has been learned yet. At the scale of six sentences neither figure means much. What matters is which of the two grows, and how fast, once the text is not six sentences, which is section 11.
In a model
The count of entries is a choice nothing later can revise. It fixes how many rows of parameters the model carries before it has read a word, and it fixes the width of the final layer that has to pick one entry out of all of them, so a model over the 48-entry table here would carry roughly a quarter more of both than one over the 38-entry table, on the same six sentences.
Keep in mind
Check yourself
Questions on Parts 1 and 2
Question 1 of 5
Two token numbers that sit next to each other hold pieces that are related.
Part 3. Where the Pieces Come From
8. The sentence one character at a time
The smallest units worth using are the characters themselves. Every character of the six sentences becomes an entry, spaces and punctuation included, which gives 37 entries. The running sentence then becomes 51 numbers, one for each character it contains, and the space carries a number of its own like everything else.
D r . ␣ A l v a r e z ␣ d i d n ' t ...
11 29 5 1 10 24 33 15 29 19 37 1 18 23 18 26 2 31Two things follow from a table this small. The first is that almost nothing is ever unseen, since a new sentence in the same language is spelled out of letters the corpus has already met. The second is that a single character carries almost no information about the writing, so a model reading this stream has to learn that the seven characters A l v a r e z in that order are a name, and it has to learn that before it can learn anything about the person.
Keep in mind
9. The sentence one whole word at a time
The other end of the trade is to make every run of non-space characters an entry. The six sentences give 47 of those, and the running sentence becomes seven numbers. Each number now carries a great deal, since low-cost arrives as one thing rather than as eight characters a model must reassemble.
What it costs is visible in the table itself. Because the cut happens only at spaces, the full stop rides along on the last word, so the six sentences give both re-analysis at 31 and re-analysis. at 32 as separate entries, and both She at 5 and she at 39, and both The at 6 and the at 43. Three pairs out of 47 entries hold one word twice over, and each of those six entries has a row of parameters learned from half the text it should have had.
Keep in mind
10. Sequence length is what everything downstream pays in
The running sentence is 51 numbers one way and 7 the other, a little over seven times as many, on the same writing. That ratio is the second of the two numbers a scheme is judged on, and it is the one a model’s running cost is measured against.
| cut into | entries in the table | numbers the sentence becomes |
|---|---|---|
| single characters | 38 | 51 |
| whole words | 48 | 7 |
The two costs move in opposite directions on the same six sentences, which is the whole of the trade the rest of this section navigates.
In a model
A model that lets every position read every other position does a piece of work for each pair of positions, so its cost grows with the square of the sequence length. Counting the pairs for the running sentence under each rule shows what that does to a ratio of seven.
pairs of positions, by character 51 × 51 = 2,601
pairs of positions, by word 7 × 7 = 49
2,601 / 49 ≈ 53Seven times as many numbers is roughly fifty times the work by that measure, on a sentence a person reads in a second. Any fixed limit on how much text a model can hold at once is also a limit in numbers rather than in words, so the same limit holds seven times less writing under the character scheme.
Keep in mind
11. Which of the two tables is smaller
Character tables are described everywhere as the small ones, and over enough text they are. Over a little text they are not, and the crossover is worth seeing because it is the reason a small experiment can point the wrong way. I fed the six sentences in one at a time and measured both tables after each.
…
After the first sentence the character table holds 25 entries and the whole-word table holds 8, so the character table is three times the size. It stays larger through the fourth sentence, 37 against 30. Between the fourth and the fifth the lines cross, and by the sixth they are 38 against 48. The character line has almost stopped moving, because the six sentences use 375 characters in all and draw them from an alphabet that was nearly complete after four of them.
The word line has not slowed at all, and it is still adding eight entries a sentence at the sixth.
›Why one line flattens and the other does not
The set of characters a language writes with is finite and small, so a table over it fills up and then stops. The set of words is not bounded in the same way, since compounds, names, numbers and inflections keep arriving, and any list of them drawn from a finite corpus is missing the next sentence’s words. That is the growth Heaps described, a count rising as a power of the amount of text read, which slows without ever flattening.
Keep in mind
Check yourself
Questions on Part 3
Question 1 of 4
Measured on these six sentences, the character table is the larger of the two for four of them.
Part 4. The Piece It Has Never Seen
12. A vocabulary is finite and writing is not
Everything so far assumed the piece being looked up is in the list. The interesting case is the other one, and it is not rare. The same growth measurement says how often it happens. Fitting on the first five sentences and then reading the sixth, which those five have never seen, 8 of its 12 words are absent from the word table while 1 of its 60 characters is absent from the character table.
| table built from | unseen in the next sentence, by character | unseen in the next sentence, by word |
|---|---|---|
| 1 sentence | 5 of 62 | 7 of 10 |
| 2 sentences | 6 of 71 | 8 of 12 |
| 3 sentences | 2 of 60 | 7 of 9 |
| 4 sentences | 0 of 71 | 11 of 13 |
| 5 sentences | 1 of 60 | 8 of 12 |
Each row encodes the sentence that has not arrived yet against tables that have never met it.
The character column falls to nothing at the fourth sentence and then rises by one at the fifth, because the sixth sentence opens with a capital S and the five before it never used one. The word column does not fall at all. Two thirds of an ordinary sentence is missing from a word table built on five sentences, and the reason the same thing does not happen at the scale of a million words is only that the fraction gets smaller, never that it reaches zero.
Keep in mind
13. Substituting a stand-in
The common answer is to reserve one entry that means “something else” and hand its number back for anything the list does not hold. That is the extra entry both tables on this page carry, sitting at number 0, and it is why 47 distinct words come to 48 entries. Every text then encodes, whatever is in it, and nothing ever refuses.
…
The first two blocks are the cost. Both sentences are seven words long, both use six words the table holds, and each has one word it does not, so both come out as the same seven numbers. A model shown either of them is shown the identical input.
Keep in mind
14. What the stand-in throws away
It is worth being precise about what is lost, because the loss is total rather than partial. The number 0 does not carry a blurred version of calibration. It carries nothing about it at all, not its length, not its letters, not whether it was a name or a verb. Reading the numbers back gives the same sentence for both, with the same gap in the same place.
The calibration drift was larger than expected.
The temperature drift was larger than expected.
both → 6 0 15 47 27 42 20
back → The [UNK] drift was larger than expected.Notice how mild this looks on these two sentences and how bad it would be on a page where the unseen words are the names, the quantities and the technical terms, which is exactly where unseen words concentrate. The words a corpus has already met many times are the common ones, so the pieces a stand-in swallows are disproportionately the ones carrying the content.
Keep in mind
15. Refusing instead
The other answer is to have no such entry and refuse. The same 47 words without a reserved entry give a table of 47, and putting the same sentence to it produces no encoding at all, with the piece it could not place named. That is the third block above.
Refusing is not obviously worse. It is louder, which is usually what one wants from a mistake, and it can be the correct behaviour rather than a limitation. A scheme whose pieces are guaranteed to cover every possible text should never reach a stand-in, so giving it one would hide a fault in the cutting rule behind a plausible-looking encoding. What refusing costs is that it is now the caller’s problem, and a system that has to answer something cannot simply decline to read the input.
| answer at an unseen piece | what it buys and what it costs |
|---|---|
| one reserved entry | every text encodes, and nothing ever fails. All the pieces it stands for become indistinguishable, and they are the rare ones. |
| refuse | the failure is visible at the moment it happens, and can be handled deliberately. Something upstream now has to handle it, and a system that must answer cannot. |
| make the case unreachable | no reserved entry is needed, because the pieces cover every text by construction. The pieces are then small, so sequences are long, which is the cost section 10 measures. |
Keep in mind
16. The table that can never meet an unseen piece
The third answer deserves its own section, because it is the one that shows the other two are choices rather than necessities. Text stored on a computer is a sequence of bytes, and there are exactly 256 possible byte values, so a table of all 256 spells every text that can be written and needs no reserved entry and no corpus to be built from.
Put the sentence that carries two letters the six sentences never used to each of the two tables. The character table substitutes twice and gives back [UNK]ngstr[UNK]m where the writing said something else. The byte table has nothing unknown to it, comes back exactly, and pays for that in length, 71 numbers against the character table’s 69, because the two accented letters take two bytes each.
Counting the same sentence both ways
A plain English letter, digit, space or mark is stored as one byte. A letter outside that basic set is stored as more than one, and the two accented letters here take two each.
Dr. Alvarez didn't expect the low-cost re-analysis in Ångström units.
characters 69
Å two bytes, 195 and 133
ö two bytes, 195 and 182
everything else 67 characters, one byte each
bytes 67 + 2 + 2 = 71The character table counts 69 pieces and has no entry for two of them. The byte table counts 71, and every one of the 71 is a value from 0 to 255, which the table held before it had read anything. Nothing was added to it for this sentence, and nothing would be added for a sentence in any other script.
Keep in mind
Part 5. The Round Trip
17. Encoding the sentence and reading it straight back
The sharpest test of a scheme is to encode a text and decode the numbers immediately, with no model in between, and compare what comes back against what went in, character for character. Anything the scheme discards shows up as a difference, and nothing else does.
…
The running sentence comes back exactly under both rules, and it is the weakest of the three cases, since it has one space between every pair of words and uses only pieces the six sentences already held. The two texts below it are where the schemes part.
Keep in mind
18. The spacing the word scheme never held
The second text is the running sentence with one doubled space and one line break in place of a space. Under the whole-word rule it still becomes the same seven numbers, none of them unseen, and it still decodes without complaint. What comes back has single spaces everywhere and no line break, so it is a different string from the one that went in.
This is not a fault that could be fixed by a bigger table. The whole-word rule keeps runs of non-space characters and keeps nothing about what lay between them, so the information was discarded at the cut and no amount of learning downstream recovers it. Gluing with a single space is a guess made once and applied everywhere.
Keep in mind
19. A letter the corpus never used
The character rule fails the same two texts for a different reason. On the second text it becomes 52 numbers, one of them the stand-in, because the line break is a character these six sentences never contained, and what comes back has the doubled space preserved and the line break replaced. On the third text it substitutes twice, for the two accented letters.
The distinction between the two failures matters. The character rule could round trip both texts perfectly if the corpus it was built from had contained a line break and an accent, so its failure is a fact about this corpus. The whole-word rule could not round trip the second text however much text it had been built from, so its failure is a fact about the rule. When a scheme reports a loss it is worth asking which of the two kinds it is, since only one of them goes away with more data.
Keep in mind
20. What a round trip can and cannot preserve
Put the two together and the rule is short. A scheme reproduces exactly what it both keeps and can spell, and nothing else. Keeping means the cut did not discard it; spelling means the table holds the pieces it was cut into.
It follows that any scheme which normalises anything cannot round trip exactly, and this is a choice rather than a defect. Folding capitals together makes The and the one entry instead of the two this page has, which is one fewer row of parameters and twice the text to learn it from, and it makes the capital unrecoverable. Later pages in this section normalise a good deal more than case, rewriting quotation marks and escaping characters, and each of those rewritings is a place where the writing that comes back is not the writing that went in. The honest way to describe such a scheme is to say what it discards, not to claim it is lossless.
Keep in mind
Part 6. Where the Idea Stops Being Defined
21. The four things any scheme has to settle
Everything on this page reduces to four questions, and every page after it answers the same four differently. Carrying them is enough to read the rest of the section, and enough to compare two schemes that describe themselves in quite different language.
| the question | what turns on the answer |
|---|---|
| what are the pieces | characters, whole words, bytes, or pieces learned from a corpus. This fixes how many entries the table has and how many numbers a sentence becomes, and those two move against each other. |
| how are they found | a fixed rule about the writing system, a list somebody wrote down, or a procedure trained on a corpus. A trained procedure inherits whatever that corpus was, including its language and its subject. |
| what happens at a piece it has never seen | a reserved entry, a refusal, or a guarantee that the case cannot arise. Each is paid for, in lost distinctions, in a failure the caller must handle, or in sequence length. |
| is the round trip exact | whether decoding the numbers gives back the original string character for character. Any normalisation at all means no, and a scheme may reasonably want the normalisation. |
The two schemes on this page, answered
| question | single characters | whole words |
|---|---|---|
| what are the pieces | each character | each run without spaces |
| how are they found | the corpus’s characters | the corpus’s words |
| at an unseen piece | one reserved entry | one reserved entry |
| round trip exact | yes, if the table has met every character | no, the spacing is not kept |
| entries | 38 | 48 |
| numbers per sentence | 51 | 7 |
Keep in mind
22. What is undefined, and what has to be chosen
Some of what a scheme has to settle is a genuine choice between defensible answers, and some of it is a case where the idea simply does not extend. The two are worth separating, since arguing about the second is wasted effort. The table gathers both, with what the mathematics says in each.
| the case | what is undefined, or what must be decided |
|---|---|
| a piece the list does not hold | undefined, and unavoidable. A list is finite and the set of things that can be written is not, so the case arises for every scheme whose pieces are not guaranteed to cover every text. There are three answers and each costs something, which is section 15. |
| a number outside the list | undefined, with no choice attached. A table of 48 entries owns the numbers 0 to 47, and 48 names no piece, so there is nothing to decode. This is the case a model generating numbers can walk into, since nothing about a generated number guarantees it is in range. |
| a text with nothing in it that counts as a piece | defined, and it is the empty run of numbers. Three spaces become no numbers under the whole-word rule and three numbers under the character rule, and the difference is what each rule counts as a piece rather than a disagreement about the text. |
| the same piece listed twice | undefined, because the number of a piece is its position and a piece in two positions has two numbers. Whichever is used, everything learned about that piece is split across two rows, so the list has to hold each piece once and be checked for it. |
| the reserved entry, decoded | defined, and it is not the writing it stood for. It decodes to its own spelling, since nothing about what was there survived the substitution. Two texts differing only in an unseen word decode to the identical string, which section 14 measures. |
| a scheme that normalises, round tripped | no longer exact, by construction rather than by accident. Folding two spellings onto one entry is the discarding of the difference between them, and the difference cannot be reconstructed from an entry that no longer records it. |
| closeness between two numbers | meaningless. The numbers are positions in a list, so a difference between two of them is a fact about the ordering of the list and nothing else. Making nearness mean something requires giving each entry a position in a space, which is a separate construction and the subject of the last pages of this section. |
| changing the list after training | well defined and silently wrong, which is the harder failure of the two. Inserting or removing an entry shifts the numbers of everything after it, so every shifted piece points at a row learned for a different piece, and the model goes on running and answers worse. |
Keep in mind
Check yourself
Questions on Parts 4 to 6
Question 1 of 5
What does the reserved entry at number 0 carry about the word it stood in for?
Try it with Botie
Build with Botie
Write and run Python