Visualizing type-based word vectors
Eight years ago I wrote a post called Word embeddings: the (very) basics. It apparently struck a chord, because people still find it, still link to it, and occasionally still email me about it. This is gratifying, and also slightly embarrassing, because eight years is a long time in NLP. Some of the things I wrote back then were already simplifications. Others have since become quaint in the way that explaining what a “CD-ROM” is has become quaint. The field has moved. The models have moved. My hairline has moved, though not in the direction I would have chosen. So, a follow-up was overdue. And because I cannot seem to be able to explain anything these days without eventually building something, the follow-up comes in the form of a Shiny app.
Why type-based word vectors, and why now?
Let me back up for the benefit of anyone who did not read the 2018 post, or who read it, correctly identified it as simplistic, and decided not to come back until I produced something more serious.
A distributional semantic model (also known as a DSM) is, at its core, a formalization of a very old intuition in linguistics, one usually traced back to J.R. Firth’s 1957 remark that “you shall know a word by the company it keeps.” The idea is that words which appear in similar contexts tend to have similar meanings. Dog and cat both turn up near pet, food, vet, fur, allergic. They appear less frequently near quarterly earnings or ballistic trajectory. This distributional similarity is a signal, and a surprisingly powerful one, about semantic relatedness.
A modern DSM turns this intuition into geometry. Each word is represented as an array of numbers, a vector, and placed as a point in a high-dimensional space. Words with similar distributions end up close to each other in that space, and crucially, that proximity is measurable and computable. You can measure it with cosine similarity. You can subtract vectors and add them. You can ask, with a straight face and a surprising degree of success, whether king − man + woman ≈ queen. The directions in the space encode relationships (gender, capital cities, verb tense) that nobody explicitly programmed in.
“DSM” covers two somewhat different families of model. Older, count-based approaches (like LSA) build vectors directly from co-occurrence statistics. Newer, prediction-based models (like Word2Vec or GloVe) learn vectors by training a neural network to predict words from their contexts. Both honor the same distributional hypothesis. They just operationalize it differently. Most introductions today lead with the prediction-based family, since those are the vectors that tend to impress people, but I think understanding the prehistory of word vectors is worth it.
Whether any of this constitutes a theory of meaning is a question for philosophers of language. Whether it is useful for empirical linguists is a question I have spent several years attempting to answer.
My own published work has used these vectors in two quite different ways. In an article in Studia Neophilologica (Desagulier, 2019), I asked whether word vectors could help corpus linguists do things they were already doing, specifically, semantic annotation of increasingly large datasets. The answer, hedged as it must be, was: yes, with caveats and a working knowledge of the limitations.
More recently, in a Cognitive Linguistics article (Desagulier, 2022), I used a Word2Vec Skip-Gram model for a diachronic study, one I took the time to fine-tune on English from the 1800–2010 period, a project I owe entirely to the COVID lockdown, which turned out to have at least one productive use. Using a contemporary off-the-shelf model for historical data would have been the equivalent of carbon-dating with the wrong isotope so, technically, a result but not necessarily a meaningful one. The question was whether complex prepositions denoting internal location (in the middle of, in the midst of, in/at the heart of, and so on) had shifted their collocational preferences over time. To find out, I extracted 300-dimensional vectors for the collocate nouns that fill the complement slot of each construction, mapped them onto a reference space distinguishing concrete from abstract/figurative locations, and overlaid frequency-based density maps for four consecutive periods in the Corpus of Historical American English (COHA). The result is a visual record of semantic drift, which is either very elegant or very nerdy, depending on your disposition, and possibly both. A second paper in Cognitive Linguistics (co-authored this time) based on a similar technique is in press as I write this, so I will not say more about it, but the short version is that I remain convinced these vectors are genuinely useful analytical tools rather than just a flashy import from computational linguistics.
The reason I keep coming back to them is not fashion. It is that they capture something intuitively real about lexical organisation. The geometry of the semantic space is not arbitrary. It reflects the structure of usage. And for a usage-based linguist like me, that is precisely where meaning lives.
A brief account of what fastText actually does
The vectors this app uses come from the fastText project at Meta AI Research. Let me be specific about what that means, because “fastText vectors” is one of those phrases that gets used loosely.
The relevant papers are Mikolov et al. (2017) and Grave et al. (2018). Here is what they actually did, stripped of the marketing. Mikolov et al. trained continuous bag-of-words (CBOW) models, which predict a target word from its surrounding context. This sounds simple, and architecturally it is. What makes their 2017 paper interesting is the combination of enhancements they brought together.
Position-dependent weighting assigns a separate reweighting vector to each position in the context window, so the model knows that the word immediately to the left of the target is not the same kind of evidence as the word four positions to the left. This is a small thing. It is also exactly the kind of thing that matters empirically.
They also incorporated subword information (character n-grams of length 3 to 6) so that a word like unhelpfulness is represented not as a single opaque token but as the sum of its parts: unh, nhe, hel, help, and so on. This handles morphologically complex languages much better than whole-word models, and it handles out-of-vocabulary items gracefully: if the model has never seen unhelpfulness, it can still produce a reasonable vector for it from the n-grams it has seen.
The training data is staggering: 9.2 billion words from Wikipedia and 630 billion words from Common Crawl. One detail worth mentioning is that sentence deduplication turns out to matter enormously for web-crawled data. The web, it turns out, is full of copy-paste. Removing duplicates before training produces measurably better vectors. This is the kind of finding that makes you feel better about your own writing, at least briefly.
Grave et al. (2018) extended this approach to 157 languages, which is why the app supports not only English, French, German, and Spanish, but also Albanian, a choice that is less eccentric than it looks, given that Albanian has a linguistically interesting morphology and, this is in fact the true reason, that one of my PhD students is working on this language. The challenge for low-resource languages is that Wikipedia is often too small: Hindi Wikipedia, for instance, contains only 39 million tokens, which is fine for an MA thesis and not fine for training a decent DSM. The solution was to bring in Common Crawl, processed through a fast language detector (itself a fastText classifier, which is a pleasingly recursive arrangement). For Finnish and Hindi, adding Common Crawl improved accuracy on analogy tasks by over 20 points. For Spanish, Wikipedia alone was better, because noise levels in web-crawled data begin to matter once you have enough text to be selective about quality. These are the kinds of trade-offs that empirical linguists should know about when they reach for a pre-trained model.
The upshot: the vectors visualized in this app are 300-dimensional fastText CBOW vectors, trained on Wikipedia and Common Crawl, with subword features and position weighting. They are, by any reasonable measure, among the best freely available static word vectors for the languages they cover. They are also several gigabytes each, which is the source of most of the engineering headaches described below.
Type-based vectors: a (partial) defence
Before moving on to the app itself, a word about the epistemological status of what we are visualising, because this matters, and because I have been asked about it often enough that I should probably write it down somewhere permanent.
fastText vectors, like their Word2Vec predecessors, are type-based representations. Each word form gets exactly one vector, computed as an aggregation over all the contexts in which that form appeared during training. Bank, financial institution and river edge, gets one vector. Bat, the thing used in baseball and the thing that lives in your attic and gives you rabies, gets one vector. The model has read both senses in training, averaged over them in some non-trivial way, and produced a single point in geometric space. One vector per word form. This is what I called the “one vector per word” problem in Desagulier (2019), and it is a real limitation.
The obvious alternative is a token-based model. BERT (Devlin et al. 2019) and its descendants produce a separate representation for every occurrence of a word in context, which means bat-the-mammal in one sentence and bat-the-sporting-equipment in another are in principle distinguishable. In theory this is exactly what a semanticist wants: as many representations as there are contexts, sensitive to polysemy, capable of detecting functional-semantic change at the level of individual uses. In practice, however, token-based models come with their own set of complications.
The base BERT model was pre-trained on the BooksCorpus (800 million words) and English Wikipedia (2.5 billion words). This means its representations are biased towards contemporary standard written English. If your research involves historical data, non-standard varieties, or specialist registers, BERT’s priors are working against you. Fine-tuning is possible, as you can post-train BERT on your own corpus to improve its behaviour on the texts you care about. But for large historical corpora the computing cost is substantial, and only portions of the data are typically usable for fine-tuning in any case (Fonteyn 2020).
There is also a transparency problem. Word2Vec, and fastText, are not black boxes. You can inspect what the algorithm is doing at every stage: the training objective is explicit, the vector arithmetic is interpretable, the hyperparameters have documented and understood effects on the output. BERT, in contrast, offers access to only the last two hidden layers in most standard implementations, and when more layers are accessible there remains genuine disagreement in the literature about which layer is semantically informative and for what purpose. For a linguist who wants to know not just what the model says but why, this matters.
fastText adds something Word2Vec does not have: subword information. Because each word vector is the sum of character n-gram vectors, the model has a partial solution to one of the harder aspects of the aggregation problem. Morphologically related forms, such as run, running, runner, runs, share n-gram components and therefore end up with vectors that are geometrically close even when the training corpus contains few examples of the rarer forms. This does not solve the homonymy problem (bank still gets one vector) but it handles morphological family relationships more gracefully than whole-word models, and it produces sensible vectors for words the model has never seen as complete forms. In the context of multilingual work or work on morphologically rich languages, this is not a minor benefit.
The deeper point, which I argued in my 2022 Cognitive Linguistics paper and which I continue to believe, is that the aggregated representation offered by a type-based model may in fact capture something real: the core meaning of a word type, the stable semantic content that persists across the variation in its contexts of use (Erk and Padó 2010: 92). Whether you find this persuasive depends partly on your theory of meaning: a Wittgensteinian will be more comfortable with it than a strict contextualist. But empirically, the consistency of the vector spaces I have worked with suggests that the aggregation is not merely noise. Semantically related words cluster. Paradigmatic substitution sets emerge. Diachronic change is detectable. These are not accidents.
None of this means fastText is the right tool for every question. If you are studying sense disambiguation, or modelling the contextual variability of a highly polysemous word, a token-based model is probably what you want. If you are working at the level of type-frequency, paradigmatic organisation, or semantic field structure, which covers a considerable portion of what corpus linguists actually do, a type-based model with good hyperparameter choices is a reasonable and defensible instrument. The computing cost is trivial by comparison, the interpretability is high, and the results, as I hope the visualisations in this app prove, are coherent enough to be worth taking seriously. Type-based distributional models have not said their last word.
The app: what it does and why I built it this way
The app has a simple purpose: load a fastText .bin model, give it a list of words, and produce a t-SNE visualisation of the corresponding vectors. t-SNE (t-distributed Stochastic Neighbour Embedding) is a dimensionality reduction technique that projects high-dimensional data into two dimensions while attempting to preserve local neighbourhood structure (van der Maaten, Hilton, 2008). In the resulting plot, words that are semantically close in the full 300-dimensional space tend to appear close in the two-dimensional projection. Clusters emerge. Sometimes they surprise you. This is, I maintain, a genuinely useful way of exploring semantic organisation. Not a replacement for rigorous corpus analysis, but an excellent way of generating hypotheses and checking intuitions.
The implementation choices were all driven by one practical reality: the models are big. The English fastText model is approximately 7 GB compressed. Uncompressed, the .bin file is around 7.2 GB. R does not enjoy loading 7 GB of anything. Neither does the person waiting for it. So here is how I dealt with this, and the issues I found along the way.
Loading: do it once, keep it in memory
The fastTextR package’s ft_load() function reads a .bin model into RAM. This takes between one and three minutes on a typical machine. You absolutely do not want to do this every time a user changes a slider or adds a word to their list. The solution is to store the loaded model in a Shiny reactiveValues object (v$model in the code) and only reload it when the user explicitly clicks the “Load Model” button. Everything downstream (word lookup, t-SNE, plotting) then works from the in-memory object. This pattern is standard reactive programming hygiene, but it is worth stating explicitly because the temptation to reload on every input change is real.
Downloading: do not let R time out!
The default network timeout in R is 60 seconds. A 7 GB download over a typical academic network connection will take considerably longer than 60 seconds. The original version of the app would therefore stop partway through the download, leave a corrupted .gz file on disk, and report an error that was, charitably, uninformative. The fix is one line:
options(timeout = 3600)
Set before the download call, this extends the timeout to one hour, which is more than sufficient. I restore the original timeout afterward with on.exit(options(timeout = old_timeout)), because leaving a one-hour timeout as a permanent side effect would be like leaving the heating on when you go on holiday.
The other download-related improvement is decompression. The original code used a manual R loop to read the .gz file in chunks and write the decompressed output. This works, but R’s I/O loop is not the fastest thing in the world when you are pushing 7 GB through it. Replacing it with R.utils::gunzip() is significantly faster and also simpler to read because it delegates to a compiled implementation.
Dealing with out-of-vocabulary words
The ft_word_vectors() function, when given a word that is not in the model’s vocabulary, returns an all-zero vector rather than throwing an error. This is technically defensible (a zero vector is a neutral, uninformative response) but it causes problems downstream: the t-SNE will happily project zero vectors into the space alongside real ones, which produces a spurious cluster at or near the origin, and the user will have no idea why châtain ended up where it did.
The fix is to detect zero rows after retrieval (rowSums(abs(vecs)) == 0), remove them, report the culprits to the user via a visible warning banner, and proceed with the remaining words. If so many words are OOV that fewer than four valid vectors remain, the app says so and declines to plot rather than producing nonsense.
t-SNE perplexity
t-SNE has a perplexity parameter that roughly controls how many neighbours each point tries to account for. The mathematical constraint is that perplexity must be less than one-third of the number of data points. With a small word list and a generous perplexity setting, this constraint is violated, and the underlying Rtsne function throws an error. The original code capped perplexity at floor((n-1)/3) but did not enforce a floor, so with very small lists the cap could return 1, which is below Rtsne‘s own minimum and causes a different error. The fix: max(2, min(input$perp, floor((n-1)/3))), with a status message telling the user that the cap was applied and what value was actually used.
Font size and label overlap
These are not bugs; they are missing features. The original plot used geom_text() with a fixed vjust offset and no size control. Two problems follow from this. First, with more than about fifteen words, labels start colliding, and the plot becomes illegible. Second, users have no way of adjusting the text size to suit their screen or their intended output.
The solution to the first problem is ggrepel::geom_text_repel(), which uses a force-directed algorithm to move labels away from each other and away from their points. It is not perfect. With very many words in a small space it will still produce a crowded result. But it is substantially better than the alternative. A checkbox lets users toggle between repelled and plain labels, because there are cases where the plain version is preferable (the repelled labels sometimes move quite far from their points, which can be confusing in dense plots).
The solution to the second problem is a slider. The label size and point size are now independent controls, both adjustable from the sidebar.
PNG export
Added with ggsave(). Users can set resolution, width, and height before downloading, which means the exported file can be production quality (300 dpi for a paper appendix) or screen quality (72 dpi for a slide that does not need to be printed). The filename is auto-generated with a timestamp and the language code, so you do not end up with three files all called plot.png overwriting each other.
A quick walkthrough
The app follows a strict left-to-right, top-to-bottom logic: the sidebar runs through five numbered steps, each of which depends on the one before it. If you skip a step, the app tells you. This is intentional.

When you first open the app, the main panel shows the status bar (“Ready. Please select a language and download/load a model.”) and an empty plot area. The sidebar already shows Step ① with the language dropdown defaulting to English and the destination folder defaulting to your current working directory. Nothing is broken; nothing has happened yet. This is what the app looks like before you have done anything, which is worth documenting because it is more informative than a blank screen.
Screenshot 2: Step ① — Downloading a model
Select a language from the dropdown.

The path field in Step ② updates automatically to reflect your choice: if you select French and your folder is /Users/you/models, the path becomes /Users/you/models/cc.fr.300.bin without you having to type anything. Click Download / Check Model. A progress bar appears in the bottom-right corner of the browser window.

If the model already exists on disk, the status bar reports this immediately and the download is skipped. If not, expect 5–20 minutes depending on your connection. Go and do something else. The app will still be there.

Once the download is complete, click Load Model into RAM. The status bar changes to “Loading model into RAM… (may take 1–3 min for large .bin files)”. This is not a freeze; it is R reading several gigabytes of binary data into memory, which takes as long as it takes. When it finishes, two things happen: the status bar confirms the loaded language, and the word list in Step ③ is automatically populated with a set of suggestions appropriate to that language: king, queen, man, woman, dog, cat, apple, orange, computer, laptop for English; roi, reine, homme, femme, chien, chat for French; and so on. These suggestions exist solely to give you something to plot immediately, before you have thought of a more interesting word list.

The word list field accepts any comma-separated list of words. As you type, a small counter below the field shows how many words have been detected: green if you are above the minimum of four, red if you are not. Words that the model does not recognise (out-of-vocabulary, or OOV) are not flagged here. They are caught later, when the vectors are actually retrieved. For most common words in a well-resourced language like English, OOV is not an issue. For informal borrowings, nonce words, or highly specialised terminology, it may be.
Screenshot 5: Step ④ — Plot settings and generation
The four controls in this step (perplexity, label font size, point size, and the label-repulsion toggle) are all adjustable before you click Generate Visualisation.

The plot does not update automatically as you move the sliders; it only renders when you click the button. This is deliberate: re-running t-SNE on every slider change would mean waiting 5–10 seconds every time you nudge the font size by half a point, which is not a trade-off worth making. Set your parameters, then click once.
A note on perplexity: for small word lists (under 20 words), keep this between 2 and 5. Higher values tell t-SNE to account for larger neighbourhoods, which is meaningless when the neighbourhood is the entire word list. The app caps perplexity automatically and tells you when it has done so.

The main panel fills with the t-SNE projection. Words that are distributionally similar in the model’s 300-dimensional space tend to appear near each other in the plot. With the default English suggestion list, you will typically see dog and cat closer to each other than either is to computer or laptop, and king and queen in each other’s vicinity. Whether this constitutes a demonstration of anything profound about language is a question the blog post addresses at some length. As a first illustration that the vectors are not random, it does its job.
The label-repulsion toggle (Step ④) is on by default. With a short word list it makes little difference; with 30 or more words it is the difference between a readable plot and an abstract painting. If labels are drifting further from their points than you would like — a side effect of the repulsion algorithm in dense regions — untick the box and use plain labels instead.

Set your DPI, width, and height in the export controls, then click Download plot as PNG. The file is saved with an auto-generated name that includes the language code and a timestamp (e.g., tsne_vectors_en_20250115_143022.png) so that successive exports do not overwrite each other. For a presentation slide, 150 dpi at 10 × 7 inches is sufficient. For a paper appendix or anything that will be printed, use 300 dpi.
A few things that the screenshots will not show but are worth mentioning in the caption text or in alt-text: the orange warning banner that appears in the main panel when OOV words have been removed; the status bar message when perplexity has been capped; and the red word-count display when fewer than four words are in the list. These are edge cases, but they are the edge cases that frustrated users of the original app, and it is worth letting readers know they are handled.
What this is good for, and what it is not
A t-SNE plot of word vectors is an exploratory tool. It is excellent for:
- Checking whether your theoretical categories are reflected in distributional data. Do the prepositions you consider semantically related actually cluster together?
- Generating hypotheses. What is that word doing over there?
- Teaching. Showing students a plot where dog, cat, hamster, and rabbit cluster together while hammer, screwdriver, drill, and wrench form a separate cluster is a remarkably effective way of making distributional semantics intuitive.
- Quickly sanity-checking a set of stimuli or a semantic field before committing to a more rigorous analysis.
It is not good for:
- Drawing definitive conclusions. t-SNE projections are not metric: distances in the 2D plot do not reliably reflect distances in the original high-dimensional space. Two words that look far apart in the plot might be moderately close in 300 dimensions. Use cosine similarity for that.
- Large-scale analysis. If you want to compare hundreds of words, a t-SNE plot becomes unreadable. You want hierarchical clustering or MCA at that point.
- Replacing corpus analysis. The vectors reflect the distributional patterns of Wikipedia and Common Crawl. Your corpus is not Wikipedia and Common Crawl. If you are working with historical data, specialist registers, or non-standard varieties, the vectors will mislead you in proportion to how far your corpus diverges from the training data. This is not a defect of the model but a property of all pre-trained resources.
Getting the app
The full script is available from my GitHub (https://github.com/GuillaumeDesa/word-vector-explorer). You will need the following packages, so install them before running the app:
install.packages(c("shiny", "shinythemes", "fastTextR",
"Rtsne", "ggplot2", "dplyr",
"R.utils", "ggrepel"))
The fastText models themselves need to be downloaded separately. The app handles this: select a language, provide a destination folder, and click “Download / Check Model.” Be patient. Make a coffee. Make a second coffee. Just kidding: on my machine, an ageing yet powerful Macbook pro 2021 with an Apple M1 Max chip and 64 Go of RAM, I barely have time to make one coffee. The download progress is displayed, though “displayed” overstates the drama: it is a progress bar, not a live commentary.
Once the model is on disk, click “Load Model into RAM.” Wait one minute (depending on your RAM). Then enter a word list, adjust the settings, and generate the visualisation.
A final reflection
I have been using word vectors in my research for the better part of a decade now. I have spent a fair amount of that time defending their use to colleagues who are, not unreasonably, sceptical of methods imported wholesale from computational linguistics into linguistics proper. The scepticism is healthy. These are not theories of meaning. They do not tell you why words have the meanings they have. They do not replace careful qualitative analysis. They are, at best, a very sensitive instrument for detecting distributional patterns. And distributional patterns, if you believe Firth and the long tradition after him, are evidence about meaning rather than meaning itself.
What I find genuinely exciting about the geometry of these spaces, and what I hope the app communicates, at least to those who pause to look at the plot rather than immediately adjusting the perplexity slider, is how much structure is there. The clusters are not random. The analogies are not accidental. The distributional hypothesis, for all its simplicity, turns out to be a powerful enough constraint to impose a rich and largely interpretable organisation on the vocabulary. That is not nothing. In fact, I think it is rather a lot, and after eight years I am still not entirely sure whether we should entirely ditch old-style vectors to only embrace context-based vectors as produced by BERT-like models.
References
Desagulier, G. (2019). Can word vectors help corpus linguists? Studia Neophilologica, 91(2), 219–240. https://doi.org/10.1080/00393274.2019.1616220
Desagulier, G. (2022). Changes in the midst of a construction network: A diachronic construction grammar approach to complex prepositions denoting internal location. Cognitive Linguistics, 33(2), 339–386. https://doi.org/10.1515/cog-2021-0128
Devlin, J., Chang, M.-W., Lee, K., & Toutanova, K. (2019). BERT: Pre-training of deep bidirectional transformers for language understanding. In Proceedings of the 2019 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies (Vol. 1, pp. 4171–4186). Association for Computational Linguistics. https://aclanthology.org/N19-1423
Erk, K., & Padó, S. (2010). Exemplar-based models for word meaning in context. In Proceedings of the ACL 2010 Conference (Short Papers) (pp. 92–97). Association for Computational Linguistics. https://aclanthology.org/P10-2017
Fonteyn, L. (2020). What about grammar? Using BERT embeddings to explore functional-semantic shifts of semi-lexical and grammatical constructions. In F. Karsdorp, B. McGillivray, A. Nerghens, & M. Wevers (Eds.), Proceedings of the Conference on Computational Humanities Research (CHR 2020) (pp. 257–268). https://hdl.handle.net/1887/138612
Grave, E., Bojanowski, P., Gupta, P., Joulin, A., & Mikolov, T. (2018). Learning word vectors for 157 languages. In Proceedings of the Eleventh International Conference on Language Resources and Evaluation (LREC 2018). Miyazaki, Japan: European Language Resources Association (ELRA). https://aclanthology.org/L18-1550/
Mikolov, T., Grave, E., Bojanowski, P., Puhrsch, C., & Joulin, A. (2017). Advances in Pre-Training Distributed Word Representations. arXiv preprint arXiv:1712.09405. https://arxiv.org/abs/1712.09405
van der Maaten, L., & Hinton, G. (2008). Visualizing data using t-SNE. Journal of Machine Learning Research, 9(86), 2579–2605. http://jmlr.org/papers/v9/vandermaaten08a.html
Licence
CC BY-NC 4.0. Use it, adapt it, attribute it.
The text only may be used under licence Creative Commons Attribution Non Commercial 4.0 International. All other elements (illustrations, imported files) are “All rights reserved”, unless otherwise stated.
OpenEdition suggests that you cite this post as follows:
Guillaume Desagulier (April 29, 2026). Visualizing type-based word vectors. Around the word. Retrieved July 26, 2026 from https://doi.org/10.58079/165i4


orcid.org/0000-0003-4895-0788