Neighbouring Words
Words by the Numbers
Chapter 4 ยท Neighbouring Words
Words by the Numbers 3 ended by saying that real language identifiers look at groups of letters, not single ones. The same step works for words: stop counting words one at a time and count the pairs and triples that sit next to each other. Some pairs are just common words that happen to be common (of the); others are pairs that stick together far more than their parts would explain (floating point). Telling the two apart is the whole chapter. The maths is light: multiplication, division, a square root and a base-2 logarithm, all done by Python.
pydoc_data.topics module), about 74,500 word tokens of technical English; it is not typical prose, and its counts change a little between Python versions, so expect small differences on your machine. Word pairs never cross from one documentation topic into the next. The tiny sentences in the first snippet and in Exercise 1 are invented, illustrative examples. Background facts come from web searches that returned summaries of web pages; such fetched pages are often truncated or model-summarised, so treat the wording as a paraphrase. A search confirmed the details of the Church and Hanks paper and the low-frequency weakness of the association score used below; it did not return anything on Firth or Halliday, so those two attributions are my recollection and are marked (check). Statements marked (check) were not confirmed against a source.
Pairs and Triples of Words
A bigram is two neighbouring words, a trigram is three, and the general name is n-gram. Making them takes one trick: line the list of words up against itself shifted by one place, and zip the two lists together. A text of n words has n − 1 bigrams and n − 2 trigrams, because the last word has no right-hand neighbour.
The sentence has 12 words, so 11 bigrams and 10 trigrams. the cat is the commonest bigram, with a count of 2, because the cat turns up twice. Everything else about n-grams is this same idea scaled up, so the real question is what the counts tell you.
The Commonest Pairs Are Dull
Run the same idea over the whole documentation text. The snippet builds word, bigram and trigram counts, prints how many different bigrams and trigrams there are, how many appear only once, and the top few of each.
The top bigrams are the pairs you would predict from Words by the Numbers 2: small grammatical words next to each other (of the, in the, to the). The documentation also shows its own habits: in version and changed in version come from the repeated notes of the form “Changed in version 3.x” (the version text is my reading of the output; check). Notice the last point about sparsity: 53% of the bigrams, and 66% of the trigrams, occur exactly once. The more words you glue together, the more of the possible combinations you have never seen.
| Unit | Distinct kinds | Seen only once |
|---|---|---|
| Words | thousands (Words by the Numbers 2) | a large share of the kinds (check) |
| Bigrams | 27,520 | 53% |
| Trigrams | 46,967 | 66% |
Collocations
A collocation is a pair (or longer group) of words that go together more than their meanings alone would require. The idea has a famous slogan, usually credited to the British linguist J. R. Firth: you shall know a word by the company it keeps (my recollection; the exact wording and year not confirmed; check). A standard textbook illustration, usually credited to M. A. K. Halliday, is that English speakers say strong tea and heavy rain, but not powerful tea (also from memory; check). Nothing in the meaning of strong forbids strong rain; it is simply not what people say. Dictionary makers care about this, and in 1990 Kenneth Church and Patrick Hanks published a paper in Computational Linguistics (volume 16, pages 22 to 29, per the search result) proposing to estimate such word associations automatically from large text collections, using a measure based on mutual information. That measure is the one coming up.
More Than Chance
To say a pair is “more than chance” you need a figure for chance. Suppose the words were shuffled into random order. Word a makes up a share c(a) ÷ N of the text and word b makes up c(b) ÷ N, so the pair a b should turn up about c(a) × c(b) ÷ N times, the expected count. Compare it with the count actually seen. The usual way to compare is a ratio on a log scale, pointwise mutual information (PMI): log2(seen ÷ expected). A PMI of 0 means chance, 1 means twice as often as chance, 2 four times, and so on.
Even of the beats chance: 532 seen against about 109 expected, a ratio near 4.9 (PMI 2.29). That makes sense, because English grammar does put the after of more often than a shuffle would. The more important lesson is in the last three lines. With no minimum count, the top five pairs all have a PMI of 16.2 and each was seen once, and that is not a coincidence: a pair seen once between two words that each appear once has PMI log2(N), and log2(74,538) is about 16.2. Those are rare words, not collocations. Raising the minimum count to 5 gives latin capital, post mortem and triple quoted; at 30 it gives floating point, finally clause and except clause, which really are the kind of fixed phrase you hoped to find. The search I ran says the same thing about PMI in general: it tends to favour low-frequency events, so it is usually paired with a frequency threshold.
| Minimum count | Top pair found | What it shows |
|---|---|---|
| 1 | generation phase (seen once, PMI 16.2) | rare words sitting together by accident |
| 5 | latin capital (seen 5 times, PMI 13.9) | real phrases, but narrow ones |
| 30 | floating point (seen 36 times, PMI 9.8) | established technical phrases |
Does a Shuffle Agree?
The expected count is an arithmetic shortcut. You can also test it directly: shuffle the words inside each documentation topic, count the pairs again, and see what a text without word order produces. If floating point really is a phrase, shuffled text should almost never produce it. The same snippet also computes a second score, the t-score: (seen − expected) ÷ √seen. It rewards pairs that are both clearly above chance and frequent, so it needs no hand-picked minimum beyond a small floor of 5.
A shuffle (one seed, so one run, not an average) makes of the 112 times, close to the expected 109, and floating point zero times against 36 in the real text. The t-score list is almost the opposite of the PMI list: it is topped by of the, in the and in version, because those are frequent and reliably above chance, while PMI preferred rare, tightly bound pairs. Neither is wrong; they answer different questions.
| Score | Favours | Top of the list here |
|---|---|---|
| Raw count | common words next to each other | of the, in the, to the |
| PMI | tightly bound but rare pairs; needs a minimum count | floating point, finally clause (minimum 30) |
| t-score | frequent pairs clearly above chance | of the, in the, in version |
Write a short invented passage of your own (two sentences). Build its bigrams and trigrams, then print how many words, bigrams and trigrams it has, how many bigrams are distinct, the commonest bigrams, and every word that follows one chosen word.
๐ View solutionOn the documentation text, print the six commonest bigrams by raw count, then the six commonest that contain none of a list of small common words, then the six best by PMI among pairs seen at least 10 times. Which list looks most like a list of phrases?
๐ View solutionShuffle the words inside each documentation topic twenty times, with a different random seed each time. For four chosen pairs, report the real count, the highest count any shuffle produced, and how many shuffles matched or beat the real count.
๐ View solutionQuick Reference
- Bigrams, trigrams:
zip(words, words[1:])andzip(words, words[1:], words[2:]); n words give n − 1 and n − 2 - Sparsity: longer n-grams repeat less (here 53% of bigrams and 66% of trigrams were seen once)
- Expected count of a pair:
count(a) * count(b) / N - PMI:
math.log2(seen / expected); 0 is chance, 1 is twice chance; always set a minimum count - t-score:
(seen - expected) / math.sqrt(seen); favours frequent pairs - Shuffle test:
random.shuffle(words)inside each document, then recount - Caution: a pair above chance is not necessarily a phrase; look at the list yourself