GloVe
Suppose you want a computer to know that "ice" is to "solid" as "steam" is to "gas". This kind of reasoning demands word vectors. These vectors must encode fine-grained semantic relationships, not just crude similarity. Word2Vec Skip-gram learns such vectors by predicting context words from a sliding window. It makes one local prediction at a time. But it never directly looks at the full statistics of the corpus. GloVe asks a different question. What if we first compute the entire word-word co-occurrence matrix for the whole corpus? Then we fit vectors to explain that matrix directly. This shift matters because it reframes embedding learning as a global matrix factorization problem. This contrasts with a local prediction problem. It unites two historically separate lines of work in distributional semantics. These are count-based methods like latent semantic analysis, and prediction-based neural methods like Skip-gram. GloVe (Global Vectors) shows that the ratios of co-occurrence probabilities carry the semantic signal. This signal supports analogies. It designs a weighted least-squares objective for a specific purpose. The goal is to make dot products of word vectors recover the logarithm of co-occurrence counts. In production systems, GloVe vectors became a standard, freely downloadable starting point for NLP pipelines. This was true throughout the mid-2010s. Sentiment classifiers, named-entity recognizers, and machine translation systems were routinely initialized with pretrained GloVe embeddings. This continued before contextual models like ELMo and BERT took over. Understanding GloVe is valuable even today. It makes the connection between co-occurrence statistics and vector geometry mathematically explicit. This connection motivates later work on Embedding Geometry and Analogies. This article derives the GloVe objective from first principles. It gives exact pseudocode for training. It proves why the weighting function is shaped the way it is. It also traces through a small worked numeric example. This makes every step of the algorithm transparent.
- GloVe factorizes a global word–word co-occurrence matrix rather than predicting words from local context windows.
- The key insight: ratios of co-occurrence probabilities, not raw counts, expose meaningful semantic relationships.
- The training objective is a weighted least-squares regression: dot products of vectors should approximate log co-occurrence counts.
- A weighting function down-weights rare and extremely frequent pairs, controlling both noise and dominance by stop words.
- Training cost is linear in the number of nonzero entries of the co-occurrence matrix, not in corpus length or vocabulary squared.
- GloVe vectors support the same linear analogy arithmetic (king − man + woman ≈ queen) that made Skip-gram vectors famous.
GloVe learns word vectors whose dot-product differences reproduce the log-ratios of global co-occurrence probabilities, turning distributional statistics into linear vector arithmetic.
GloVe: Global Vectors for Word Representation
The idea
A co-occurrence matrix over a fixed vocabulary is built by scanning the corpus once with a context window of some fixed size, and incrementing every time word appears within that window of word . Let be the total count of words that ever co-occur with , and let be the probability that word appears in the context of word . This matrix is exactly the "distributional profile" underlying Distributional Semantics: two words are similar if their rows of look alike. GloVe's central empirical observation is that raw probabilities are dominated by frequency effects and are not very informative alone, but ratios across a third "probe" word discriminate meaning sharply. Consider , . For , the ratio is large, since "solid" co-occurs much more with "ice" than "steam". For , the ratio is small. For , a word related to both, or , a word related to neither, the ratio is near 1. This behavior is exactly the signal needed to place "ice" and "steam" correctly relative to "solid" and "gas" in vector space, and it motivates modeling this ratio directly rather than modeling alone. GloVe therefore posits a function of word vectors and context vector such that
Through a sequence of well-motivated simplifications — requiring to depend only on the vector difference (so that vector space is linear in the relevant direction), requiring the arguments to combine via a dot product (so that the function is invariant to how we split the difference across dimensions), and requiring symmetry between a word and a context word (so word and context vectors play interchangeable roles) — the derivation collapses to
with scalar bias terms absorbing marginal frequency effects (including ). This is the GloVe model equation: it says the dot product of a word vector and a context vector, plus two biases, should reconstruct the log co-occurrence count. Fitting all vectors to satisfy this equation, weighted appropriately, is the entire training objective.
How it works
Step 1 — Build the co-occurrence matrix. Scan the corpus once with a symmetric context window of size (e.g., 10 words on each side). For each center word and each context word found within the window at distance , increment by (distance weighting reduces the influence of far-away words). This produces a large but very sparse matrix, since most word pairs never co-occur.
Step 2 — Define the weighted least-squares loss. The full objective sums over all nonzero entries of :
Here is the "word vector" for word , is the separate "context vector" for word , and is a weighting function that must satisfy three properties: (so the sum over the sparse matrix stays finite as ), non-decreasing (so frequent co-occurrences are not down-weighted relative to rare ones), and bounded / eventually small for very large (so extremely common pairs like "the"/"of" do not dominate the loss). GloVe uses
with typical values , .
Step 3 — Optimize with stochastic gradient descent (or AdaGrad). Each training step samples one nonzero entry and updates by gradient descent on the per-pair squared error, scaled by . AdaGrad is preferred in the original implementation because co-occurrence counts span many orders of magnitude, and per-parameter adaptive learning rates handle this scale variation better than a single fixed rate.
Step 4 — Combine word and context vectors. After training, GloVe forms the final embedding for a word as (sum of the word vector and its own context vector), which empirically works slightly better than using alone, acting as a form of implicit ensembling over the two nearly-redundant vector sets. ```
# GloVe training algorithm Input: corpus, vocabulary V, window size L, embedding dim d, x_max, alpha, learning_rate, num_epochs
# ---- Step 1: build sparse co-occurrence counts ---- X = empty sparse map from (i, j) -> float, default 0 for each position p in corpus: i = word at position p for each position q in [p - L, p + L], q != p, within corpus bounds: j = word at position q d = |p - q| X[(i, j)] += 1.0 / d # closer context words weigh more pairs = list of (i, j, X[(i,j)]) for all nonzero entries # O(nnz) pairs
# ---- Step 2 & 3: initialize parameters and train ---- for each word k in V: w[k] = random small vector in R^d w_tilde[k] = random small vector in R^d b[k] = 0.0 b_tilde[k] = 0.0 grad_sq_w[k] = ones(d) # AdaGrad accumulators grad_sq_wt[k] = ones(d) grad_sq_b[k] = 1.0 grad_sq_bt[k] = 1.0 def weight(x): if x < x_max: return (x / x_max) ** alpha else: return 1.0 for epoch in 1..num_epochs: shuffle(pairs) total_loss = 0 for (i, j, Xij) in pairs: pred = dot(w[i], w_tilde[j]) + b[i] + b_tilde[j] diff = pred - log(Xij) fij = weight(Xij) loss = fij diff diff total_loss += loss
# gradient of f diff^2 w.r.t. each parameter grad_common = 2 fij diff # scalar factor shared below g_w = grad_common w_tilde[j] # d(loss)/d(w[i]) g_wt = grad_common * w[i] # d(loss)/d(w_tilde[j]) g_b = grad_common # d(loss)/d(b[i]) g_bt = grad_common # d(loss)/d(b_tilde[j])
# AdaGrad updates grad_sq_w[i] += g_w g_w grad_sq_wt[j] += g_wt g_wt grad_sq_b[i] += g_b g_b grad_sq_bt[j] += g_bt g_bt w[i] -= learning_rate g_w / sqrt(grad_sq_w[i]) w_tilde[j] -= learning_rate g_wt / sqrt(grad_sq_wt[j]) b[i] -= learning_rate g_b / sqrt(grad_sq_b[i]) b_tilde[j] -= learning_rate g_bt / sqrt(grad_sq_bt[j]) report(epoch, total_loss)
# ---- Step 4: final embedding ---- for each word k in V: embedding[k] = w[k] + w_tilde[k] return embedding ``` Every gradient in the pseudocode is a direct application of the chain rule to : differentiating the square gives the factor , and differentiating the linear inner term with respect to leaves exactly (and symmetrically for ), while the bias derivatives are .
Complexity & correctness
Building the co-occurrence matrix requires one pass over a corpus of tokens with a window of size , giving time — linear in corpus size, exactly like Skip-gram's window scan. The resulting matrix has at most entries but in practice has nonzero entries, since co-occurrence follows a heavy-tailed (roughly Zipfian) distribution: most word pairs simply never appear together in any window.
Training performs a constant amount of work — one dot product, one squared-error gradient, four AdaGrad updates, each for embedding dimension — per nonzero entry, per epoch. Total training time is therefore
which is independent of raw corpus length once the co-occurrence matrix is built: a corpus can be scanned once, its statistics cached, and then GloVe trained repeatedly at a cost governed only by the matrix's sparsity, not by how many tokens the corpus contained. This is the practical efficiency argument for global-count methods: expensive corpus scanning happens once, and the optimization reuses compressed statistics ( pairs) as many times as needed, whereas Skip-gram's stochastic training must revisit the raw token stream (or its negative-sampling equivalent) on every epoch.
Space is for the sparse matrix plus for the two vector sets (word and context) and biases — the same order as the vocabulary times embedding dimension needed by any embedding method.
Correctness argument. The claim to justify is not "GloVe converges" in a generic optimization sense — the loss is a sum of smooth non-convex terms in the joint parameters (since it involves a product ), so standard gradient descent on only guarantees convergence to a stationary point, exactly as with matrix factorization objectives in general. The deeper correctness claim is about why the model equation is the right one to fit. The derivation proceeds by these logical steps: 1. Start from the requirement that some function of vectors reproduces the informative ratio: . 2. Since vector spaces are naturally linear, restrict to depend on the vector difference: . This encodes the idea that the direction " minus " should carry the meaning distinguishing them relative to any probe . 3. The arguments of are vectors but the right-hand side is scalar; a dot product is the natural scalar-valued bilinear map, giving . 4. Requiring to be a group homomorphism between and — because swapping the roles of should invert the ratio, and the difference negates — forces , giving
5. Expanding and absorbing (a function of alone) plus a symmetrizing bias into learned bias terms yields exactly the GloVe model equation . So the model equation is not an arbitrary regression target — it is the unique consequence (under the stated, individually well-motivated restrictions) of requiring the vector space to linearly encode co-occurrence-probability ratios. The weighted least-squares loss is then simply the natural way to fit this equation robustly across a matrix whose entries vary over many orders of magnitude, with preventing the few very large counts (mostly involving function words) from dominating the squared-error sum, and preventing zero-count pairs (which are not even summed) from being treated as informative negative evidence, unlike Skip-gram's explicit negative sampling.
Tradeoffs. GloVe requires materializing and storing the co-occurrence matrix, which costs memory upfront and does not scale as gracefully to streaming or online settings as Skip-gram's token-by-token training. It also treats co-occurrence counts within a fixed window as the only signal, discarding word order beyond that window in a way that both GloVe and vanilla Skip-gram share. Both methods produce static embeddings — one vector per word type — which cannot represent polysemy (e.g., "bank" the river edge vs. "bank" the institution get one blended vector), a limitation that later motivated contextual embeddings.
Worked example
Consider a tiny toy corpus (ignoring window-distance weighting for clarity, using window size 1, unweighted counts) over four words: `ice`, `steam`, `solid`, `water`. Suppose the resulting co-occurrence counts (already symmetrized) are:
| pair | ||
|---|---|---|
| (ice, solid) | 20 | 3.00 |
| (ice, water) | 8 | 2.08 |
| (steam, solid) | 2 | 0.69 |
| (steam, water) | 9 | 2.20 |
With : weights are
Suppose after some epochs of training the (illustrative, rounded) fitted 2-dimensional vectors are:
| word | vector |
|---|---|
| ice | |
| steam |
| context | vector | bias |
|---|---|---|
| solid | 0.1 | |
| water | 0.0 |
with word biases , . Check the model equation on (ice, solid):
Compare to : the residual is , so gradient updates would push and further apart in the direction that raises their dot product, weighted heavily since gives full weight to this correction. Now check (steam, solid):
Compare to : residual , but this pair only contributes weight , so its gradient contribution is damped relative to (ice, solid) even though the raw residual is smaller in magnitude — this is precisely the weighting function doing its job, since a count of 2 is noisier evidence than a count of 20 and should influence the fit less per unit of squared error. After many such updates across all pairs, the fitting pressure pulls `ice` toward directions shared with `solid` and away from directions shared with `gas`-like words, and symmetrically for `steam`. The final embedding for "ice" is , combining its role as a center word and (if it also appears as a context word for other centers) its role as a context word.
Common pitfalls & traps
| Pitfall | Why it happens | Fix |
|---|---|---|
| Treating zero-count pairs as "negative evidence" | The loss only sums over nonzero ; zeros are simply absent, not penalized | Understand this as an implicit assumption of "missing at random" for unseen pairs; do not add explicit negative terms |
| Wrong choice of | Too small saturates for most common pairs, losing discrimination among frequent words; too large lets stop-word pairs dominate | Tune on held-out analogy or similarity benchmarks; the paper's is a corpus-dependent default, not universal |
| Forgetting to symmetrize or double count | Co-occurrence is naturally symmetric ( from 's perspective should relate to from 's), but window-scanning code can silently only count in one direction | Explicitly increment both and during the window scan, or store the matrix as symmetric by construction |
| Using alone instead of | The two vector sets are trained somewhat redundantly but not identically; using only one discards signal | Follow the original recipe: sum word and context vectors for the final embedding |
| Comparing GloVe and Skip-gram on raw loss values | The two objectives are on entirely different scales (log-count regression vs. log-likelihood of binary classification) | Compare only on downstream tasks (analogies, similarity, classification accuracy), never on raw training loss magnitudes |
| Ignoring that both are static embeddings | Practitioners sometimes expect GloVe to disambiguate polysemous words | Use contextual models when word-sense disambiguation matters; GloVe assigns exactly one vector per word type |
Pioneers & history
Origins · 1 minJeffrey Pennington and how this was discovered
Trained originally in physics before moving into machine learning, Pennington brought a physicist's instinct for deriving models from invariance principles — exactly the style of the ratio-based derivation that produces the GloVe model equation from symmetry requirements on .
Where this matters
Pretrained GloVe vectors (trained on corpora such as Wikipedia, Gigaword, and Common Crawl, at scales up to 840 billion tokens) were, for years, a default initialization layer in production NLP systems: sentiment analysis, part-of-speech tagging, named-entity recognition, and early neural machine translation encoders all commonly loaded GloVe vectors as a frozen or fine-tunable embedding layer. Recommendation systems and search engines have adapted the same global co-occurrence factorization idea to user–item and query–document matrices, since the underlying mathematical structure (sparse count matrix, weighted least-squares factorization) transfers directly. The core lesson — that ratios of co-occurrence statistics, not raw counts, carry semantic signal, and that a carefully weighted regression can recover that signal efficiently — continues to inform how practitioners think about the geometry of embedding spaces, a topic developed further under Embedding Geometry and Analogies. GloVe also remains a standard pedagogical bridge between classical count-based Distributional Semantics and the neural prediction objectives used in Word2Vec Skip-gram and its descendants.
Ask the tutor: Why does requiring the function to be a group homomorphism force it to be the exponential function in the GloVe derivation?
How is GloVe different from Word2Vec Skip-gram at a mechanical level?
Skip-gram trains by sliding a window over the corpus and, at each position, performing a local prediction task: given a center word, predict which words appear nearby, contrasted against sampled negative words. It never explicitly builds a full co-occurrence matrix; the matrix is implicit in the stream of training examples. GloVe instead performs the window scan once to build an explicit sparse co-occurrence matrix, then optimizes a weighted least-squares objective over that matrix's nonzero entries. Both methods use two vector sets (word and context) and both produce comparable-quality static embeddings, but GloVe's training cost scales with the number of distinct nonzero co-occurrence pairs rather than with the number of corpus tokens processed per epoch.
Why does GloVe use two separate vector sets, w and w̃, for the same vocabulary?
The derivation of the model equation treats a word playing the role of "center" and a word playing the role of "context" asymmetrically inside the ratio , so the cleanest mathematical fit keeps two independent parameter sets rather than forcing . This mirrors Skip-gram, which also maintains separate input and output embedding matrices for the same underlying reason: a word's distribution over what appears near it need not be symmetric with its distribution as something appearing near other words. After training, GloVe recombines the two roles by summing for the final embedding, which empirically slightly improves quality, likely by averaging out independent noise from the two nearly redundant estimates.
Does the weighting function f make the GloVe loss convex?
No. The loss is non-convex in the joint parameters because the term is a bilinear (product) interaction between two sets of learned vectors, the same structural source of non-convexity found in classical matrix factorization objectives like those in recommender systems. The weighting function only reshapes how strongly each residual contributes to the gradient; it does not change the underlying bilinear structure. In practice, AdaGrad-based stochastic optimization reliably reaches good local optima empirically, but there is no global convergence guarantee, and different random initializations can produce embeddings with slightly different geometry (though similar downstream quality).
Can GloVe handle words that never co-occur within the chosen window?
If two words never appear together within the context window anywhere in the corpus, their entry is exactly zero and is simply excluded from the sum in the loss — GloVe never penalizes the model for any particular dot-product value on that pair. This is different from Skip-gram with negative sampling, which explicitly samples negative (non-co-occurring) pairs and pushes their dot products down. As a consequence, GloVe relies entirely on the shape of the surrounding nonzero entries to indirectly position such word pairs correctly relative to each other, rather than on any explicit repulsive signal.
Why does summing word and context vectors improve the final embedding?
Empirically, Pennington, Socher, and Manning found that using rather than alone gives modestly better performance on word analogy and similarity benchmarks. A plausible explanation is that and are trained on overlapping but not identical objectives (one models word as a center, the other as a context), so each contains some independent estimation noise around a shared underlying semantic signal; summing acts like averaging two noisy estimates of the same latent quantity, reducing variance. This is analogous to ensembling techniques elsewhere in machine learning, where combining multiple noisy but correlated predictors improves the aggregate estimate.
Is GloVe still used in modern NLP systems?
Static embeddings like GloVe have largely been superseded by contextual embeddings from transformer-based language models for state-of-the-art accuracy, because GloVe assigns exactly one fixed vector per word regardless of context and cannot disambiguate polysemous usages. However, GloVe remains useful as a lightweight, fast, and interpretable baseline, in resource-constrained settings where running a large transformer is impractical, in educational contexts for teaching embedding geometry, and as a component in some information-retrieval and lexical-similarity pipelines where full contextualization is unnecessary overhead. Its mathematical clarity also makes it the standard teaching example for connecting co-occurrence statistics to vector arithmetic.
What role does the bias term play in the GloVe model equation?
The bias terms and absorb word-specific and context-specific frequency effects that would otherwise have to be encoded awkwardly in the dot product. Recall the derivation: , and the term depends only on word , not on the pair, so it is exactly the kind of quantity a per-word scalar bias can represent without consuming any of the vector's directional capacity. Without bias terms, the vectors would have to encode both directional/semantic information and raw frequency magnitude simultaneously, which would distort the geometry that later supports clean linear analogies.