This report covers the first stage of building a predictive text application — software that guesses the next word you are about to type, the way a phone keyboard does.
The raw material is three large collections of English text scraped from blogs, news sites and Twitter. Before any prediction can happen, we need to know what is actually in that text: how big it is, how words are distributed, and which word sequences are common enough to be worth remembering.
The three headline findings are:
These facts are good news: they mean the prediction model can be made small and fast enough to run in a web app without storing the whole corpus.
| Source | Size (MB) | Lines | Words | Characters | Longest line (chars) | Words per line (mean) |
|---|---|---|---|---|---|---|
| blogs | 200.4 | 899,288 | 37,334,131 | 206,824,505 | 40,833 | 41.5 |
| news | 196.3 | 1,010,242 | 34,372,530 | 203,223,159 | 11,384 | 34.0 |
| 159.4 | 2,360,148 | 30,373,583 | 162,096,241 | 140 | 12.9 |
Three sources, three very different shapes. Twitter has by far the most lines but the shortest ones — the old 140-character limit is clearly visible in the “longest line” column. Blogs contain a single entry over 40,000 characters long.
Reading Figure 1: tweets cluster around 10–20 words and stop hard. News and blog entries have a long tail of much longer passages. A prediction model trained only on news would be poorly suited to short, informal typing — which is exactly what users of a phone keyboard do — so we keep all three.
The full corpus does not need to be processed to understand it. We draw a 2% random sample of lines from each file, which keeps the analysis representative while letting the whole report run in a couple of minutes.
| Sampled lines | Sampled words |
|---|---|
| 85,705 | 2,066,319 |
Before counting anything we clean the text: strip URLs, Twitter handles and hashtags, drop numbers and punctuation, and lower-case everything. Profanity is removed so the finished app never suggests an offensive word.
Note: common words such as “the”, “and” and “to” are kept. In most text analysis they are discarded as noise, but here they are the point — a next-word predictor must be able to suggest them.
The patterns are exactly what everyday English looks like: the, to, and, a at the top; of the, in the, for the as pairs; thanks for the, one of the, a lot of as triples. Common conversational phrases such as “thanks for the follow” come straight from the Twitter portion.
This is the single most important question for keeping the app small.
| Coverage of all word occurrences | Distinct words required |
|---|---|
| 50% | 140 |
| 75% | 1,410 |
| 90% | 6,858 |
| 95% | 15,358 |
| 99% | 50,444 |
The curve rises almost vertically and then flattens. In plain terms: we can throw away the overwhelming majority of the vocabulary and still understand almost every sentence a user types. Roughly 6,858 words cover 90% of everything written. That single fact is what makes a phone-sized model possible.
A related finding: about 48% of distinct words appear only once in the sample — misspellings, usernames, one-off slang. They carry almost no predictive value and will be dropped.
The idea in one sentence: given the last few words you typed, look up which word most often came next in the corpus, and offer that.
How it will be built:
data.table objects. Target:
under ~100 MB in memory, well within the free
shinyapps.io limit.How we will know it works: the corpus is split into training and held-out test portions. On the held-out text we measure top-1 accuracy (was the actual next word our first guess?) and top-3 accuracy (was it in our top three?), plus the average response time, which must stay comfortably under a tenth of a second.
The finished app will be a single Shiny page: a text box where the user types, three suggested next words shown as clickable buttons, and a small panel showing how confident the model is. Simple enough that no explanation is needed to use it.
Code for this report is available on request; all analysis was
performed in R using the quanteda text-analysis
package.