Contents Language as Data Code Course home

Chapter 3The Empirical Laws of Text

Counting words, seriously

Before this book fits a single model, do something that sounds too simple to be scientific: take a large body of text, count how often each word occurs, and then stare at the counts. This is the cheapest experiment in natural language processing, since a few lines of shell script will do it, and it also produces one of the most consequential findings in the field.

Language is wildly and lawfully unbalanced, and every system we build afterwards either respects that imbalance or is quietly broken by it.

Run the experiment on any sizeable English corpus and the same picture appears, with a handful of words such as the, of, and, to and a taking a startling share of all running text.

The Brown corpus makes a good witness, and this chapter measures it repeatedly. Every figure comes from autograder/nlp_pipeline.py, which is the tokeniser and fitting code Project 1 is graded against, so the numbers here are the ones your own submission should reproduce.

Under it Brown holds 1,023,7341{,}023{,}734 tokens and 44,32444{,}324 distinct words, of which the alone accounts for 6.846.84 per cent, and the ten most frequent words together for 24.124.1 per cent.

A different tokeniser gives different totals. A stricter rule that keeps only fully alphabetic tokens, discarding the digits and the apostrophe forms that TOKEN_RE admits, drops VV to 41,15141{,}151. Neither count is wrong, and neither is comparable to the other, so state the tokeniser whenever you state a count.

At the other end of the table something stranger shows up, because almost half of all distinct words occur exactly once. In Brown the figure is 39.539.5 per cent, with 54.354.3 per cent occurring twice or fewer. These singletons have a name, hapax legomena, which is Greek for “said once”, and their sheer abundance is the first sign that word frequency does not behave the way intuition expects.

Two clarifications before we go on, because the vocabulary of counting causes endless confusion. A token is a running occurrence of a word and a type is a distinct word, so the sentence “the cat saw the dog” has five tokens but four types, because the occurs twice. Everything in this chapter is a statement about how types and tokens relate.

Zipf’s law

Order the types by frequency, most frequent first, and give each one a rank, so that the most frequent word has rank 1, the next has rank 2, and so on.

George Kingsley Zipf did this in the 1930s, by hand and in heroic quantity, and he found that frequency and rank trade off almost exactly inversely:

f(r)≈Crα,α≈1,(3.1)\begin{equation} f(r) \;\approx\; \frac{C}{r^{\alpha}}, \qquad \alpha \approx 1, \label{eq:zipf} \quad\text{(3.1)} \end{equation}

where f(r)f(r) is the frequency of the rank-rr word and CC is a constant of the corpus.

Read literally, that says the second word is about half as frequent as the first, the tenth about a tenth as frequent, and the hundredth about a hundredth.

A power law is a straight line

Take logarithms of both sides. Equation (3.1) becomes

log⁡f(r)=log⁡C−αlog⁡r,(3.2)\begin{equation} \log f(r) \;=\; \log C \;-\; \alpha \log r, \label{eq:zipf-log} \quad\text{(3.2)} \end{equation}

which is y=mx+cy = mx + c with y=log⁡fy = \log f, x=log⁡rx = \log r, slope m=−αm = -\alpha and intercept c=log⁡Cc = \log C.

That is the whole trick, and it is worth learning once because it keeps returning. Plot frequency against rank on log log axes and the law becomes a check you can make by eye, since if the points lie on a line then the law holds and the steepness of that line is α\alpha. Fitting the exponent is then ordinary least squares rather than curve fitting.

Every empirical law in this chapter is a power law, so every one of them becomes a line under logarithms, and so do the neural scaling laws of Chapter 18.

This is the most reproduced plot in corpus linguistics and you will draw it in Project 1, with dots hugging a descending line across three or four orders of magnitude, from the down into the fog of hapaxes.

Frequency against rank on log log axes. The line is nearly straight across four orders of magnitude. At the bottom right it breaks into flat steps, which are the words occurring twice, then once.

The line is not perfect, and its imperfections are informative. At the very top the few most frequent words sit slightly off it, while at the bottom the singletons form discrete horizontal shelves, because a word can occur once or twice but never 1.41.4 times.

Benoît Mandelbrot proposed a small correction that fits the head far better:

f(r)≈C(r+β)α,(3.3)\begin{equation} f(r) \;\approx\; \frac{C}{(r + \beta)^{\alpha}}, \label{eq:mandelbrot} \quad\text{(3.3)} \end{equation}

where the shift β\beta flattens the curve for the first few ranks.

How large β\beta comes out depends almost entirely on how much of the tail you fit, because β\beta is what absorbs the bend. On Brown:

Rank range fitted α\alpha β\beta
1…1,0001 \ldots 1{,}000 0.9668 0.00
1…10,0001 \ldots 10{,}000 1.0984 10.25
1…44,3241 \ldots 44{,}324, all ranks 1.5180 403.25

Fit the head alone and β\beta comes out exactly zero, so Mandelbrot buys nothing and plain Zipf already describes the head. Fit every rank, which is what fit_mandelbrot does, and β\beta runs into the hundreds.

A large β\beta is therefore not a verdict on your corpus but simply what a single power law needs in order to cover a curve that bends. Notice that α\alpha climbs along with it, because both are absorbing the same curvature, so quote α\alpha, β\beta and the rank range together or quote none of them.

Zipf’s own explanation for why language does this was a principle of least effort, where speakers want a small vocabulary of reusable words while listeners want a large vocabulary of precise ones, and the power law is where that tug of war settles.

Later work is a useful corrective, because surprisingly weak assumptions produce Zipf like curves, including random typing with a space bar. The law’s existence therefore tells us less than one might hope, while its consequences for us are concrete, and we return to them at the end of the chapter.

Fitting the exponent

Reading a law off a plot is not the same as measuring it, so this section fits α\alpha properly, on data you can check by hand.

The corpus is a collection of Indian budget speeches, and the frequency table gives fifteen rows covering ranks 11 through 1010 and ranks 233233 through 237237. The top word, the, occurs 59,04259{,}042 times, the word at rank 1010 occurs 9,0709{,}070 times, and the word at rank 235235 occurs 477477 times.

The first instinct is to solve for α\alpha from two points, and dividing Equation (3.1) by itself at two ranks makes the constant CC cancel:

f(1)f(10)=C/1αC/10α=10α,soα=log⁡10f(1)f(10)=log⁡106.509=0.8136.\frac{f(1)}{f(10)} = \frac{C/1^{\alpha}}{C/10^{\alpha}} = 10^{\alpha}, \qquad\text{so}\qquad \alpha = \log_{10}\frac{f(1)}{f(10)} = \log_{10} 6.509 = 0.8136.

Now test that number where it was not fitted. Predicting rank 235235 gives 59,042/2350.8136=69559{,}042 / 235^{0.8136} = 695 against a measured 477477, which makes the estimate 4646 per cent too high.

The fix is to stop throwing data away, so take logarithms and fit the line of Section 3.2.1 by least squares over all fifteen points:

α̂=−∑i(xi−x‾)(yi−y‾)∑i(xi−x‾)2,xi=log⁡ri,yi=log⁡fi.(3.4)\begin{equation} \hat{\alpha} \;=\; -\, \frac{\sum_i (x_i - \bar{x})(y_i - \bar{y})}{\sum_i (x_i - \bar{x})^2}, \qquad x_i = \log r_i, \quad y_i = \log f_i. \label{eq:zipf-ls} \quad\text{(3.4)} \end{equation}

That gives α=0.9426\alpha = 0.9426 and C=83,239C = 83{,}239, and the same test now predicts 485485 against 477477, so the error falls from 4646 per cent to under 22.

These are exactly the values fit_zipf returns on the same fifteen rows, so the procedure above is the graded one, not an illustration of it.

Fitting Zipf and Mandelbrot to the same fifteen budget speech ranks. The measured value at rank 235235 is 477477.
Method α\alpha β\beta squared error f̂(235)\hat{f}(235)
Two points, r=1r = 1 and r=10r = 10 0.8136 n/a n/a 695
Least squares, all 15 points 0.9426 0 0.0453 485
Mandelbrot, scanning β\beta 0.9843 0.5 0.0302 472

Table 1.1 adds Mandelbrot’s correction to the comparison. The shift β\beta sits inside the logarithm, so least squares cannot reach it, and the remedy is to scan β\beta, fit α\alpha and CC at each value, and keep the best. That one extra parameter buys a third off the error.

Notice that the fitted C=83,239C = 83{,}239 is larger than the observed f(1)=59,042f(1) = 59{,}042, so the line does not pass through the top word, and it should not. The head is flatter than the body, which means a fit dominated by the head understates α\alpha, and that is exactly what the two point estimate did.

Now the warning promised earlier. The Mandelbrot fit is a two parameter optimisation with a shallow valley:

β\beta best α\alpha squared error
0.0 0.9426 0.0453
0.5 0.9843 0.0302
1.0 1.0183 0.0356
2.0 1.0749 0.0643

Doubling β\beta moves α\alpha by more than three per cent while barely moving the error, so report (α,β)(\alpha, \beta) as a pair, because otherwise neither number means anything.

The exponent is not a constant

One more measurement settles what α\alpha actually is. Fit Brown over different rank ranges and the answer moves:

Rank range fitted fitted α\alpha
1…1001 \ldots 100 0.9816
1…1,0001 \ldots 1{,}000 0.9668
1…10,0001 \ldots 10{,}000 1.0726
1…44,3241 \ldots 44{,}324, all types 1.3492

The tail falls faster than the head, so a wider window gives a steeper line, and that is why the textbook claim α≈1\alpha \approx 1 is safe: it is a statement about the first few thousand ranks and nothing more.

An exponent quoted without its fitting range is not a measurement, so report the range every time.

Zipf as a probability

Equation (3.1) gives counts. Divide by the total count and it becomes a distribution over the vocabulary:

p(r)=r−αHV,α,HV,α=∑k=1Vk−α,(3.5)\begin{equation} p(r) \;=\; \frac{r^{-\alpha}}{H_{V,\alpha}}, \qquad H_{V,\alpha} \;=\; \sum_{k=1}^{V} k^{-\alpha}, \label{eq:zipf-prob} \quad\text{(3.5)} \end{equation}

where HV,αH_{V,\alpha} is the generalised harmonic number.

Where the normaliser comes from

That equation is usually read past, so it is worth slowing down. Zipf’s law assigns each rank a weight, r−αr^{-\alpha}, and weights are not probabilities, because nothing makes them sum to one and in general they do not.

HV,αH_{V,\alpha} is simply their total, so dividing every weight by it turns the weights into probabilities, since a set of numbers divided by its own sum always sums to one. Dividing changes no ratio between two words either, so the shape the law describes survives the normalisation untouched.

A vocabulary of eight with α=1\alpha = 1 makes this concrete, and the weight of rank rr is then just 1/r1/r.

rr weight r−αr^{-\alpha} p(r)=w/Hp(r) = w/H running sum
1 1.0000 0.3679 0.3679
2 0.5000 0.1840 0.5519
3 0.3333 0.1226 0.6746
4 0.2500 0.0920 0.7665
5 0.2000 0.0736 0.8401
6 0.1667 0.0613 0.9014
7 0.1429 0.0526 0.9540
8 0.1250 0.0460 1.0000
HH 2.7179 1.0000

The second column sums to 2.71792.7179 rather than to one, and that total is H8,1H_{8,1}. The third column is the second divided by it, and now it does sum to one.

With that in hand, p(r)p(r) is the chance that a token drawn at random from the corpus is the rank rr word, and summing it gives the coverage of the top kk words:

Coverage⁡(k)=∑r=1kp(r)=∑r=1kr−α∑r=1Vr−α=Hk,αHV,α.(3.6)\begin{equation} \operatorname{Coverage}(k) \;=\; \sum_{r=1}^{k} p(r) \;=\; \frac{\sum_{r=1}^{k} r^{-\alpha}}{\sum_{r=1}^{V} r^{-\alpha}} \;=\; \frac{H_{k,\alpha}}{H_{V,\alpha}}. \label{eq:coverage} \quad\text{(3.6)} \end{equation}

The middle step is the whole derivation. Summing the first kk probabilities means summing the first kk weights and dividing by the same total, and a sum of the first kk terms is precisely what a harmonic number is, so the ratio is not a trick. The numerator is the mass you keep, the denominator is all the mass there is, and both are sums of the same terms.

On the toy vocabulary, the top two words hold H2,1/H8,1=1.5000/2.7179=0.5519H_{2,1}/H_{8,1} = 1.5000/2.7179 = 0.5519, and the running sum column agrees, because it is the same arithmetic.

Why the exponent decides the tail

The normaliser also answers a question the previous section left open. What happens to coverage as the vocabulary grows?

α\alpha H1000,αH_{1000,\alpha} H106,αH_{10^6,\alpha} growth
0.8 15.47 74.81 4.84×\times
1.0 7.49 14.39 1.92×\times
1.2 4.34 5.28 1.22×\times

For α≤1\alpha \le 1 the sum diverges, so a thousand times more vocabulary keeps adding to the denominator, the coverage of any fixed kk keeps falling, and the tail never becomes negligible however much text you collect. Above one the sum converges and the head holds a stable share no matter how large VV gets.

Measured α\alpha for natural language sits close to one and usually just below it, which means language lives on the side of this boundary where the tail is permanent. That is the mathematical statement of a fact Heaps’ law states empirically in Section 3.5.1, namely that new words keep arriving forever.

Coverage counts tokens, not types

One distinction has to be nailed down before the table below, because it is where the reading usually goes wrong. A type is a distinct word in the vocabulary while a token is a word as it occurs in running text, so the sentence the cat sat on the mat has six tokens and five types, because the appears twice.

Coverage counts tokens and the size of a vocabulary counts types. Those are different units, and the distance between them is the whole content of Zipf’s law, which is why a number like “two per cent of the vocabulary” and a number like “sixty-nine per cent of the text” can describe the same cut-off and still look nothing alike.

This is also why coverage is the useful form of the law. Raw counts depend on how much text you happened to collect, so two corpora cannot be compared with them, whereas p(r)p(r) and Coverage⁡(k)\operatorname{Coverage}(k) are fractions and can be. Coverage converts a curve into a budget, and that is what makes it the single most useful number in the chapter.

How much running text the head of the vocabulary carries. Brown corpus, V=44,324V = 44{,}324, with the model column from Equation (3.6) at α=0.9668\alpha = 0.9668.
Top kk types per cent of VV coverage, model coverage, measured
10 0.02 22.51 24.09
100 0.23 41.40 47.18
1,000 2.26 62.14 69.13
10,000 22.56 84.56 92.60

Read column two against column four of Table 1.2. About two per cent of the vocabulary carries about 6969 per cent of the running text. Equivalently, discarding the rarest 7777 per cent of the types costs under eight per cent of the tokens.

The model tracks the measurement closely at the head and drifts at the tail, for the reason the previous section gave, since one α\alpha cannot bend twice.

Three later decisions rest on this table. A stop list is short because the head is short, a truncated vocabulary loses many types and few tokens, and a subword vocabulary of 32,00032{,}000 pieces spends its whole budget on the head, with Chapter 5 showing what it does with the rest.

One caveat is worth keeping in view. When α≤1\alpha \le 1 the sum HV,αH_{V,\alpha} grows without bound as VV grows, so the tail never becomes negligible however much text you add.

Heaps’ law: the vocabulary never closes

Zipf’s law describes a frozen corpus, whereas Heaps’ law describes what happens as a corpus grows.

Let NN be the number of tokens read so far and V(N)V(N) the number of distinct types seen. Empirically,

V(N)≈KNb,(3.7)\begin{equation} V(N) \;\approx\; K \, N^{b}, \label{eq:heaps} \quad\text{(3.7)} \end{equation}

with KK usually between 10 and 100, and the exponent bb usually quoted between 0.40.4 and 0.60.6 for English.

Quote the two together, because they are coupled. A fit that raises bb must lower KK to pass through the same data, so a large bb always arrives with a small KK. Pin bb on Brown and watch the best KK move with it:

bb pinned at best KK
0.40 155.93
0.50 43.17
0.60 11.95
0.5764 16.18 (both fitted freely)

So “KK between 10 and 100 and bb between 0.4 and 0.6” is one statement about a curve rather than two independent ones. Brown measures K=16.18K = 16.18 and b=0.5764b = 0.5764 in Section 3.5.1, while Figure 1.2 shows a smaller and more homogeneous corpus at b=0.78b = 0.78 with KK under two. That figure is right, because small corpora really do fit that high.

Vocabulary size against corpus size, both on log axes, with the fitted line. Here b=0.78b = 0.78 and K=1.97K = 1.97. The points climb steadily and the line never turns over, which is the property with teeth.

Two properties matter here. First, the exponent is less than one, so vocabulary growth decelerates, which means the second million tokens bring fewer new words than the first million did and doubling a corpus does not come close to doubling its vocabulary.

Second, and this is the part with teeth, the function never flattens, because a power law has no asymptote and there is no corpus size at which V(N)V(N) stops growing. However much text you collect, the next document can still hold a word you have never seen, whether a name, a typo, a coinage, a chemical formula or a hashtag. The vocabulary of a natural language is not a closed set, and any system built around a fixed word list has already decided to fail on the tail.

You will check both properties in Project 1 by plotting V(N)V(N) as your corpus streams past, and in the spirit of Section 3.8 below you will predict the curve’s shape before you draw it.

Fitting Heaps, and what extrapolation costs

Equation (3.7) linearises the same way Zipf’s law did:

log⁡V(N)=log⁡K+blog⁡N.(3.8)\begin{equation} \log V(N) \;=\; \log K \;+\; b \log N. \label{eq:heaps-log} \quad\text{(3.8)} \end{equation}

So bb is a slope, and it is also an elasticity, because doubling the corpus multiplies the vocabulary by 2b2^{b}. At b=0.5b = 0.5, four times the text gives twice the vocabulary.

Sample the vocabulary every 1,0001{,}000 tokens, which is what fit_heaps does, and fit all 1,0241{,}024 points. Five of them:

NN tokens VV types V/NV/N
1,000 468 0.4680
10,000 2,584 0.2584
100,000 12,962 0.1296
500,000 31,854 0.0637
1,000,000 43,648 0.0436

The fit gives b=0.5764b = 0.5764 and K=16.18K = 16.18. The corpus grew by a factor of a thousand while the vocabulary grew by a factor of 9393.

Fitting the full curve matters, because least squares on five hand-picked marks gives a visibly different pair and would not agree with the grader.

Now for the experiment that matters more. Fit the law on the first 100,000100{,}000 tokens only and use it to predict a corpus ten times larger, where that prefix gives b=0.7176b = 0.7176 and K=3.50K = 3.50, so

V̂(106)=3.50×(106)0.7176=70,799,against a measured 43,648.\hat{V}(10^{6}) = 3.50 \times (10^{6})^{0.7176} = 70{,}799, \qquad\text{against a measured } 43{,}648.

One decade of extrapolation, 6262 per cent too many types.

The cause is the same concavity that moved α\alpha earlier, because the exponent bb is not a constant of the language either and drifts downward as NN grows as the log log curve bends gently. Fit over the range you will actually operate in, and treat any extrapolation as an upper bound.

That the error is an over-estimate is worth noticing, since it is the safe direction for sizing an embedding table and the wrong direction for a cost estimate.

Zipf and Heaps are one fact seen twice

The two laws are not independent observations. If frequency falls as r−αr^{-\alpha}, then a word at rank rr needs roughly rαr^{\alpha} tokens of text before it appears at all. Reading that backwards, NN tokens reveal about N1/αN^{1/\alpha} distinct types, so

b≈1α,α>1.(3.9)\begin{equation} b \;\approx\; \frac{1}{\alpha}, \qquad \alpha > 1. \label{eq:zipf-heaps} \quad\text{(3.9)} \end{equation}

Brown fitted over all ranks gives α=1.3492\alpha = 1.3492, so Equation (3.9) predicts b=0.7412b = 0.7412 against a measured bb of 0.57640.5764. That is the right order of magnitude from two unrelated measurements, and not much better than that.

They do not agree exactly, and they should not, because the derivation assumes a single α\alpha holds across the whole rank range and Section 3.3 showed that it does not. The lesson is the relationship rather than the decimal places: steeper frequency decay means fewer rare words, which in turn means slower vocabulary growth.

Type token ratio and the length trap

A natural summary of lexical richness is the type token ratio

TTR⁡=VN,(3.10)\begin{equation} \operatorname{TTR} \;=\; \frac{V}{N}, \label{eq:ttr} \quad\text{(3.10)} \end{equation}

which is vocabulary size divided by text length. Rich, varied prose should score high and repetitive, formulaic text should score low, and on the whole it does.

There is a trap, though, and Heaps’ law describes it exactly. Since V≈KNbV \approx K N^{b} with b<1b < 1, we get TTR⁡≈KNb−1\operatorname{TTR} \approx K N^{\,b-1}, which falls as NN grows.

Take a 1,000 word essay and a 100,000 word novel by one author, and their TTRs will differ wildly, with the novel’s far lower, for no stylistic reason whatever. TTR is a property of a text at a length, never of the text alone.

Brown’s own fit, K=16.18K = 16.18 and b=0.5764b = 0.5764, puts numbers on that:

NN predicted TTR measured TTR
1,000 0.8673 0.4680
10,000 0.3270 0.2584
100,000 0.1233 0.1296
1,000,000 0.0465 0.0436

Same author, same style, four different answers, and the measured column is the one that matters, falling by a factor of ten.

The first row is worth pausing on, because the fitted law is good near a million tokens and poor at a thousand, since the log log curve is concave and 1,0241{,}024 points pull the line towards the large NN end. A fitted law is a summary of a curve rather than an oracle for every point on it.

The trap, measured

Table 1.3 runs the experiment on six genres of Brown. The raw column uses the whole genre. The standardised column cuts each genre into non-overlapping windows of 8,0008{,}000 tokens, computes TTR in each, and averages them.

Type token ratio for six Brown genres, raw and length corrected. The two rankings disagree.
Genre NN raw TTR rank std. TTR rank
press reportage 90,089 0.1359 3 0.3077 1
humour 18,450 0.2552 1 0.3021 2
general fiction 58,605 0.1458 2 0.2744 3
romance 58,966 0.1307 4 0.2520 4
learned 164,036 0.0885 6 0.2478 5
government 63,214 0.1106 5 0.2320 6

Raw TTR crowns humour as the richest genre in Brown, and humour is also the shortest genre in Brown, at 18,45018{,}450 tokens against 164,036164{,}036 for learned prose. The measurement is reading length rather than style.

Two rankings actually reverse. Raw TTR puts fiction above press reportage, while on equal windows press reportage wins, and raw TTR puts government above learned prose, while on equal windows learned prose wins. Neither reversal is noise, because both hold at every window size from 2,0002{,}000 tokens up to 18,00018{,}000.

The discipline that follows is simple and not negotiable. Never compare type token ratios across samples of different sizes. Compare equal length slices instead, or use a length corrected variant.

Length corrected variants

The measure used in Table 1.3 is the mean segmental type token ratio. Cut the text into mm windows of fixed size WW and average:

MSTTR⁡=1m∑j=1mVjW.(3.11)\begin{equation} \operatorname{MSTTR} \;=\; \frac{1}{m}\sum_{j=1}^{m} \frac{V_j}{W}. \label{eq:msttr} \quad\text{(3.11)} \end{equation}

It is simple and it works, and its weakness is that the answer still depends on WW, so WW must be reported and held fixed across everything being compared.

A cheaper variant is the root type token ratio, V/NV/\sqrt{N}, which is Equation (3.7) with bb forced to 0.50.5, and it only removes the length effect where bb really is near 0.50.5. Brown’s is 0.580.58, close enough to make the shortcut tempting and far enough to bias a comparison.

The honest summary of lexical richness is neither of these. It is the fitted pair (K,b)(K, b) from Section 3.5.1, which describes the whole curve rather than one point on it.

Project 1 asks you to compare your corpus against a contrast genre, and it fixes the sample size for exactly this reason. When the measured TTRs still differ, the difference is real, because legal boilerplate and technical templates repeat themselves and fiction does not.

What the laws mean for everything downstream

These three regularities look like curiosities, but they are the standing constraints under which every model in this book operates.

Which knob moves tokens, and which moves types

The laws also price the preprocessing decisions of Chapter 2. Measured on Brown, each figure a share of the raw counts:

Operation tokens left types left
Stop words removed 55.5% 99.8%
Numbers stripped 99.0% 97.5%
Porter stemming 100.0% 65.4%
Drop every type seen ≤5\le 5 times 94.1% 28.0%

Read the two columns against each other. Stop word removal takes 4444 per cent of the tokens and 0.20.2 per cent of the types, which is Zipf’s law stated as an engineering fact, because stop words are very few types carrying very many tokens.

Stemming is the mirror image, leaving every token where it is while 3535 per cent of the vocabulary collapses.

Dropping every type seen five times or fewer removes 7272 per cent of the vocabulary and costs 5.95.9 per cent of the tokens, which is the trade Table 1.2 priced and why a fixed subword vocabulary is less of a sacrifice than it looks.

One thing barely moves at all. The Heaps fit goes from K=16.18K = 16.18, b=0.5764b = 0.5764 to K=17.33K = 17.33, b=0.5958b = 0.5958 once stop words and numbers are gone, so the curve is a property of the language rather than of your cleaning.

Try it yourself. code/worked_examples/empirical_laws.py prints every fit and table in this chapter. python3 empirical_laws.py harmonic builds the normaliser on a vocabulary of eight, where every division can be checked on paper, and then shows HH diverging at α≤1\alpha \le 1. python3 empirical_laws.py mandelbrot shows β\beta climbing from 00 to 403403 as the fitting range widens. python3 empirical_laws.py heaps pins bb and watches KK move, then extrapolates a decade and misses by 6262 per cent.

Run it in ColabNotebookSource

The head motivates weighting. The most frequent words are overwhelmingly function words, and glue like the and of appears everywhere and so distinguishes nothing. Any similarity measure built on raw counts will be dominated by exactly the words that carry least content, which is the problem inverse document frequency solves in Chapter 4. At bottom, tf-idf is a machine for discounting the Zipfian head.

The tail motivates smoothing. Roughly half the vocabulary occurs once, and the exact fraction depends on corpus size, rising as the corpus shrinks. Full Brown gives 39.539.5 per cent, its news genre 4949 per cent and its science fiction 6262 per cent, and at any of those figures reliable statistics exist for almost no specific word. Events unseen in training are the normal case. That is why the zero probability problem of Chapter 10 is the central difficulty of statistical language modelling, and why no amount of patching corner cases will address it. Every model, up to the largest LLM, must reserve belief for the unseen.

Heaps’ law motivates subwords. If the vocabulary never closes then a word level system meets out of vocabulary items forever, and mapping them all to one <unk> symbol, as in Chapter 10, throws their identity away. The modern answer is to decompose rare words into pieces that are in a closed set. That is the next chapter, and it is best read as a direct engineering response to Equation (3.7).

The empirical discipline

This chapter closes with a habit rather than a law.

Every quantitative claim above is checkable in minutes on any corpus you can lay hands on, whether the slope near −1-1, the exponent near 0.50.5, or the falling TTR. This course will repeatedly ask you to predict the number before you measure it.

The point is not ritual. A prediction forces your mental model into the open where the measurement can correct it, whereas a measurement taken with no prediction slides past the mind and teaches nothing.

Calibration is knowing how far off your guesses tend to be, and it is a trainable skill as well as the difference between a practitioner who understands a system and one who merely operates it.

We start training it on word counts because word counts are cheap, and by the end of the book you will be predicting perplexities, attention patterns and retrieval failures the same way.

Further reading.

Zipf (1949), Human Behavior and the Principle of Least Effort, is still a strange and rewarding read. Manning and Schütze (1999) give the sober statistical treatment of both laws. Baayen (2001) is the modern reference for the mathematics of the tail. Both laws can be fitted in one line with numpy.polyfit or scipy.optimize.curve_fit, and the last exercise below is there because one line is enough to fit the wrong thing.

Fit Zipf. Take a corpus of your choice. A novel from Project Gutenberg is ideal. Rank the word types by frequency, plot frequency against rank on log log axes, and fit the exponent α\alpha of Equation (3.1). Report α\alpha. Say where the fit is worst, in the head, the tail, or both.

Fit twice, on purpose. Estimate α\alpha from ranks 11 and 1010 alone, using the two point formula of Section 3.3. Then estimate it by least squares over ranks 1…10001 \ldots 1000. Predict f(500)f(500) with each and compare against the measured value. Report both signed errors.

Report the range. Fit α\alpha over ranks 1…1001 \ldots 100, 1…10001 \ldots 1000 and all ranks. Give the three numbers in a table. Explain in one sentence why the widest range gives the steepest line.

Mandelbrot’s correction. Refit the head of the same distribution with the two parameter form of Equation (3.3) and report (α,β)(\alpha, \beta). The chapter warns that this fit is a shallow valley. Report the pair together, and show that a range of (α,β)(\alpha,\beta) values fit almost equally well.

Coverage, predicted and measured. Compute the coverage of the top 1010, 100100 and 10001000 words directly from your counts. Then predict the same three numbers from Equation (3.6) using your fitted α\alpha. Where does the model diverge from the measurement, and why?

The cost of a cut-off. Using your coverage numbers, find the vocabulary size that keeps 9595 per cent of the tokens. What fraction of the types does it discard? Relate your answer to the fixed vocabulary of Chapter 5.

Trace Heaps’ law. Stream the corpus token by token. Record the vocabulary size |V||V| against the token count NN, then fit the exponent of Equation (3.7). Does vocabulary growth ever stop? Connect your answer to the pressure that motivates subword tokenisation in Chapter 5.

Extrapolate and fail. Fit Heaps’ law on the first tenth of your corpus, predict VV for the whole of it, then measure. Report the signed error. Is your prediction too high or too low, and does the sign agree with the chapter?

Check the link. Take your fitted α\alpha over all ranks and your fitted bb. How close is bb to 1/α1/\alpha? Give one reason the agreement is not exact.

Type token ratio across genres. Compute the TTR of your corpus and of a second corpus from a different genre, first raw and then on equal length samples. Report whether the ranking changes. Explain in one sentence why the equal length constraint is not optional.

Choose the window. Compute the MSTTR of Equation (3.11) at W=2,000W = 2{,}000, 5,0005{,}000 and 10,00010{,}000 on the same two corpora. Do the values change? Does the ranking change? Say what that implies about reporting a single MSTTR.

Predict first. Before running any of the above, write down three things. Your predicted α\alpha. Your predicted Heaps’ exponent. Which genre you expect to have the higher TTR. Compare with your measurements and account for each surprise. This is the discipline of Section 3.8.

Where you fit changes what you get. Fit Equation (3.1) to the fifteen budget speech points twice with scipy.optimize.curve_fit. Fit it once to log⁡f\log f against log⁡r\log r, and once to the power law itself in linear space, with no logarithms anywhere. The first returns α=0.9426\alpha = 0.9426, the figure this chapter reports, and the second returns 0.70770.7077. Work out which of the fifteen measurements the second fit is really listening to, and then add the space you fitted in to the list of things Section 3.8 says you must report alongside an exponent.

Code for this chapter

Each one reproduces the tables above. Open it in Colab, change an input and watch which numbers move.

From Natural Language Processing: From Corpus Statistics to Grounded LLMs, by Ramaseshan Ramachandran.