Negative Sampling and Training Word2Vec
Suppose you want to teach a machine that "king" and "queen" share meaning. You must do this using only raw text and no labels. The Word2Vec Skip-gram model tries to do this by predicting context words from a center word. But the naive way of scoring that prediction requires a softmax over the entire vocabulary. This vocabulary can span tens of thousands to millions of terms. It must be computed for every single training example. With a vocabulary of 1,000,000 words and a corpus of billions of tokens, a full softmax turns into an intractable amount of matrix-vector work. This work gets repeated billions of times. Negative sampling solves this by reframing the learning problem entirely. Instead of asking "which of these million words is the correct context word?", it asks something cheaper. It asks a much cheaper binary question repeated many times: "is this particular (center, context) pair a real co-occurrence, or did I just make it up?" This turns an expensive multi-class classification into a handful of cheap binary classifications. It is one of the key engineering ideas that made training high-quality word embeddings feasible. This became possible on web-scale corpora in 2013. This shift is not just a speed hack. It is a principled approximation to a well-defined objective. It is closely related to matrix factorization of a pointwise mutual information matrix. It comes paired with a second trick: subsampling of frequent words. This trick improves both training speed and embedding quality. It does this by down-weighting uninformative high-frequency tokens like "the" and "of." This article gives a precise, step-by-step account of how negative sampling works inside Word2Vec. It also covers subsampling in the same detail. This includes full pseudocode, and a complexity analysis. That analysis explains exactly why the trick is asymptotically cheaper. It also includes a worked numerical trace, and the historical context that led to this design. It sets up the ground for understanding GloVe and later Embedding Geometry and Analogies.
- Full softmax over a vocabulary of size costs per training step; negative sampling replaces it with binary decisions, .
- Negative sampling turns "predict the right word among " into "distinguish real pairs from sampled fake pairs" using logistic regression.
- Negative words are drawn from a unigram distribution raised to the power , which boosts rare words relative to their raw frequency.
- Subsampling randomly discards frequent words (like "the") during training, controlled by a threshold hyperparameter, speeding up training and improving embeddings for rare words.
- The resulting objective is a biased but effective approximation to full softmax skip-gram, and is provably related to factorizing a shifted PMI matrix.
- Both tricks are what made word2vec practical at web scale, directly enabling the pipeline that leads to GloVe and to studying Embedding Geometry and Analogies.
Negative sampling replaces an expensive -way softmax classification with a cheap set of binary real-vs-fake classifications, making skip-gram training linear in the number of negative samples instead of the vocabulary size.
The idea
The Word2Vec Skip-gram model defines, for a center word and a context word , a probability
where is the "input" embedding of the center word and ranges over "output" embeddings of every word in the vocabulary . Training by maximum likelihood requires computing the denominator — the partition function — over the entire vocabulary at every step, since its gradient touches every output vector. This is the full softmax bottleneck: each single training example costs time and touches parameters.
Negative sampling (introduced alongside skip-gram as "Skip-gram with Negative Sampling", SGNS) replaces this multi-class objective with a set of independent binary classification problems. For each observed (center, context) pair, treat it as a positive example with label . Then sample random words from the vocabulary (that are not the true context word) as negative examples with label . Train a logistic classifier — using the dot product of the two embeddings as the score — to distinguish real pairs from fake ones. The key terminology: the true pair is called a positive sample, the randomly drawn words are negative samples, and (typically 5–20 for small corpora, 2–5 for very large ones) is the negative sampling rate. A second, complementary idea is subsampling of frequent words. Words like "the", "a", "is" occur so often that they contribute little information about any specific center word's meaning, yet they dominate training time and drown out the gradient signal from rarer, more meaningful words. Subsampling randomly drops instances of a word from training with a probability that grows with its corpus frequency, controlled by a threshold hyperparameter (commonly ). This both speeds up training (fewer tokens processed) and improves embedding quality (better-balanced gradient signal across the vocabulary).
How it works
The negative sampling objective
For a positive pair , define the sigmoid score
The per-pair SGNS objective, sampling negatives from a noise distribution , is
We maximize this quantity (or equivalently minimize its negation) via stochastic gradient ascent/descent. Note the sign flip inside for negatives: we want the dot product for a fake pair to be small (score close to ), which is equivalent to wanting to be close to .
The noise distribution
Negatives are not drawn uniformly nor from the raw unigram frequency , but from a smoothed unigram distribution:
Raising frequencies to the power flattens the distribution: very frequent words become relatively less likely to be sampled compared to their raw frequency, and rare words become relatively more likely. This empirically produces better embeddings — negatives that are neither trivially easy (extremely common, obviously unrelated words) nor unhelpfully obscure.
Subsampling of frequent words
Before pairs are even generated, each token in the training stream is kept with probability
a common formulation used in the reference implementation (an equivalent simplified variant is used in some expositions). Both forms share the essential shape: keep-probability decreases smoothly as frequency grows, with negligible discarding below the threshold and aggressive discarding well above it.
Step-by-step training loop
The full pipeline, combining skip-gram context generation, subsampling, and negative sampling: ``` INPUT: corpus (stream of tokens), vocabulary V with counts, embedding dim d, window size m, negatives k, subsample threshold t, learning rate eta, epochs E 1. Build vocabulary V from corpus; compute frequency f(w) for each w. 2. Precompute noise distribution: P_n(w) = f(w)^0.75 / sum_{w'} f(w')^0.75 for all w in V Build an alias table (or cumulative table) for O(1)-ish sampling from P_n. 3. Initialize input embeddings U[w] and output embeddings W[w] for all w in V, each a d-dimensional vector (small random init). 4. for epoch in 1..E: for each token position i in corpus: w_c = token at position i // --- Subsampling step --- keep_prob = compute_keep_probability(f(w_c), t) if random() > keep_prob: continue // discard this token instance // --- Dynamic window --- window = random_integer(1, m) // shrink window randomly per example context_positions = [i-window, ..., i-1, i+1, ..., i+window] (clipped to valid corpus bounds) for j in context_positions: w_o = token at position j // positive context word // --- Positive update --- score = dot(U[w_c], W[w_o]) g_pos = (1 - sigmoid(score)) // gradient coefficient grad_U = g_pos W[w_o] grad_W_pos = g_pos U[w_c] // --- Negative samples --- grad_U_total = grad_U for s in 1..k: w_n = sample_from(P_n) such that w_n != w_o score_n = dot(U[w_c], W[w_n]) g_neg = -sigmoid(score_n) grad_U_total += g_neg W[w_n] W[w_n] += eta g_neg U[w_c] // update negative's vector // --- Apply updates --- W[w_o] += eta grad_W_pos U[w_c] += eta * grad_U_total 5. return U // (or average of U and W, or U alone, per convention) ``` The gradient coefficients above follow directly from differentiating . For the positive term with ,
and for a negative term ,
Both use the identity and the chain rule; multiplying by (or the symmetric term for the output vector) gives exactly the vector updates in the pseudocode.
Complexity & correctness
Time complexity per training pair. Full softmax requires computing for every to normalize, costing per (center, context) pair, where is the embedding dimension. Negative sampling instead computes only dot products (one positive, negatives), costing , independent of . Since is a small constant (commonly 5–20) while can be to , this is a reduction from linear-in-vocabulary to constant-in-vocabulary per pair — the entire reason SGNS scales to web-sized corpora. For an epoch over a corpus of tokens with average window size , the total cost is for negative sampling versus for full softmax. With , , , , : negative sampling costs on the order of floating point multiply-adds per epoch, while full softmax costs roughly — a factor of difference, matching the ratio .
Space. Both approaches store the same parameters: two matrices (input and output embeddings), so space is regardless of the training method — negative sampling only changes the per-step compute, not the parameter count.
Why the approximation is sound. SGNS is not merely "softmax but cheaper" — it is a different but related objective with its own justification. Consider a single negative sample per positive pair for simplicity, drawn from the true unigram distribution. It has been shown (Levy & Goldberg, 2014) that maximizing the SGNS objective in expectation, for the case negative samples drawn from the unigram distribution, drives the dot product between vectors to satisfy
where is the pointwise mutual information between word and context over the corpus. This means SGNS is, in expectation, implicitly performing a low-rank factorization of a shifted PMI matrix — the same statistical quantity that count-based distributional semantics methods have long used, but learned via cheap stochastic binary classification rather than an explicit matrix decomposition. This connection is exactly what motivates comparing SGNS to GloVe, which factorizes a log-count matrix explicitly.
Correctness sketch via gradient balance. At a stationary point of the SGD dynamics, for each (center, context) pair the expected gradient must vanish. Setting the derivative of with respect to the score to zero and using smoothed frequency, one finds the balance condition
which after algebra recovers , i.e., the shifted-PMI identity above (with the caveat that in the real algorithm , not the raw unigram , is used for negatives, and the exponent slightly perturbs this ideal relationship in practice, which empirically improves embedding quality on rare words).
Honest tradeoffs. Negative sampling is a biased, approximate objective, not a strict lower bound on the true softmax log-likelihood in the way that e.g. hierarchical softmax approximations sometimes are; its quality depends on the number of negatives , the smoothing exponent, and the noise distribution shape. Too few negatives leads to underfitting the "what is not a valid context" signal; too many negatives increases cost roughly linearly with little added benefit past a point (diminishing returns are well documented empirically, with – typically sufficient). Subsampling is also a lossy heuristic: it discards information, and its keep-probability formula, while empirically well-tuned, is not derived from a clean statistical principle — it is a practical corpus-frequency correction, not a probabilistically unbiased importance-sampling scheme.
Worked example
Consider a tiny toy corpus (ignore real-world scale, this is for tracing the mechanics): ``` "the cat sat on the mat the dog barked at the cat" ``` Vocabulary (with counts): the:4, cat:2, sat:1, on:1, mat:1, dog:1, barked:1, at:1. Total tokens .
Step 1 — noise distribution. Compute for each word (raw frequency ):
| word | count | (normalized) | ||
|---|---|---|---|---|
| the | 4 | 0.3077 | 0.4285 | 0.257 |
| cat | 2 | 0.1538 | 0.2603 | 0.156 |
| sat | 1 | 0.0769 | 0.1580 | 0.095 |
| on | 1 | 0.0769 | 0.1580 | 0.095 |
| mat | 1 | 0.0769 | 0.1580 | 0.095 |
| dog | 1 | 0.0769 | 0.1580 | 0.095 |
| barked | 1 | 0.0769 | 0.1580 | 0.095 |
| at | 1 | 0.0769 | 0.1580 | 0.095 |
Note "the" drops from raw share to smoothed share — still likely to be sampled as a negative, but proportionally less dominant than its raw frequency would suggest, exactly the intended flattening effect.
Step 2 — subsampling decision for "the". Using the simplified rule with :
So roughly 99.4% of occurrences of "the" are dropped from training — it will almost never be used as a center word or (in most implementations) removed from context windows either, freeing training time for informative pairs like (cat, sat) or (dog, barked). Contrast with "cat" (): — still heavily subsampled since even "cat" is common in this tiny corpus, illustrating that subsampling is aggressive whenever is small relative to corpus size; in real multi-billion-token corpora, produces much milder, more realistic discarding for mid-frequency words while still hammering stopwords.
Step 3 — one SGNS update. Suppose after subsampling we still process the pair center = "cat", context = "sat" (positive), with negatives sampled from : suppose we draw "barked" and "on". Let embeddings be 2-dimensional for hand-tracing, with current values
Positive score: . . Gradient coefficient (we want this dot product to increase). Negative 1 ("barked"): . , so (push this dot product down further — it should be even more negative). Negative 2 ("on"): . , (this one is positive, meaning the model currently thinks "on" is a plausible context for "cat" — the gradient will push it down harder). With learning rate :
New . The update nudged "cat" only slightly since the sigmoid values were all near (an uninitialized, nearly-random embedding stage) — this is expected early in training and is the correct behavior: large, confident updates only occur once dot products diverge from zero, which is exactly what repeated SGD steps are designed to produce over many epochs.
Common pitfalls & traps
| Pitfall | Why it happens | Fix |
|---|---|---|
| Sampling the true context word as a "negative" | Naive uniform/unigram sampling can accidentally draw the actual positive word | Explicitly reject-and-resample if a drawn negative equals |
| Using raw unigram frequency for instead of the -power smoothed version | Copying softmax-style sampling without the empirical correction | Always raise frequencies to before normalizing |
| Setting far too large "for better accuracy" | Assuming more negatives always helps, ignoring diminishing returns | Use –; benchmark on a validation analogy/similarity task |
| Forgetting to subsample before windowing | Applying subsampling only to center words but leaving all context tokens in-window | Apply subsampling uniformly to the corpus stream before generating windows |
| Confusing input and output embedding matrices at inference | Some pipelines only need , others sum or average | Follow the convention documented for the specific pretrained model; don't silently mix them |
| Treating SGNS score as a true probability | The sigmoid output is calibrated for the binary sub-task, not for ranking against the full vocabulary | Do not interpret as directly; use dot-product rankings instead |
Pioneers & history
Origins · 1 minTomas Mikolov and how this was discovered
Tomas Mikolov, together with colleagues Ilya Sutskever, Kai Chen, Greg Corrado, and Jeffrey Dean at Google, introduced both the skip-gram/CBOW architectures and the negative sampling training trick in 2013. Mikolov's earlier work on recurrent neural network language models had already made him attentive to the crushing cost of softmax normalization over large vocabularies; negative sampling was the pragmatic solution that let embedding training scale from academic-sized corpora to the entire Google News dataset (about 100 billion words) in days rather than months on the hardware of the time.
Where this matters
Negative sampling's core idea — replace an expensive full-normalization objective with cheap binary discrimination against sampled negatives — extends far beyond Word2Vec. It underlies contrastive learning broadly, including modern sentence and document embedding methods, retrieval systems (dense passage retrieval for search engines, where a query must be scored against millions of documents using in-batch or hard negatives instead of a full corpus softmax), and recommendation systems (candidate generation models that must rank against catalogs of millions of items). The Skip-gram-style objective and its negative sampling training recipe are reused, with modifications, in graph embedding methods (node2vec, DeepWalk) that treat graph random walks the same way skip-gram treats sentences. Pretrained static word embeddings trained this way (word2vec, fastText) are still used as fast, low-resource baselines and as initialization or auxiliary features in some production NLP pipelines where full contextual transformer models are too costly to serve. Studying this mechanism directly prepares the ground for GloVe's explicit matrix-factorization alternative and for understanding Embedding Geometry and Analogies, since the shifted-PMI interpretation of SGNS explains why linear analogy structure (king − man + woman ≈ queen) emerges from these training objectives at all.
Ask the tutor: How does changing the negative sampling exponent from 0.75 to 1.0 (raw frequency) change the embeddings learned for rare words?
Why not just use full softmax if it's the mathematically "correct" objective?
Full softmax is not wrong, just computationally prohibitive at scale. Each gradient step requires normalizing over the entire vocabulary, meaning cost per training example grows linearly with vocabulary size, often – words. With corpora of billions of tokens, this becomes computationally infeasible on commodity hardware. Negative sampling and related tricks like hierarchical softmax were developed specifically to make training tractable while approximately preserving the objective's useful properties — namely, that words with similar contexts end up with similar embedding vectors. The tradeoff is a biased, approximate objective in exchange for orders-of-magnitude speedup, which in practice yields embeddings of comparable or even better empirical quality on analogy and similarity benchmarks.
How is negative sampling different from hierarchical softmax, another common Word2Vec speedup?
Both address the softmax normalization bottleneck but differently. Hierarchical softmax organizes the vocabulary into a binary tree (often a Huffman tree weighted by frequency) and computes the probability of a word as the product of binary decisions along the tree path from root to leaf, costing per example rather than . Negative sampling instead abandons the tree structure entirely and reframes the task as binary classification against sampled negatives, costing per example. Empirically, negative sampling with small tends to train faster and produce better embeddings for frequent words, while hierarchical softmax can be preferable for rare words, since it still models a proper (if tree-structured) probability distribution.
Does the number of negative samples matter a lot in practice?
Yes, though with diminishing returns. Increasing generally improves embedding quality up to a point because the model sees more contrastive signal about what is not a valid context per positive example, but each additional negative also costs additional compute linearly. The original word2vec paper found between 5 and 20 worked well for smaller datasets, while between 2 and 5 sufficed for very large datasets (billions of tokens), since with enough total training pairs, the model already sees enough negative evidence across the whole corpus even with few negatives per individual example. Choosing is thus a tradeoff tuned against total corpus size and compute budget.
What does subsampling actually remove, and could it hurt rare-word learning?
Subsampling removes tokens probabilistically, most aggressively removing instances of very frequent words like function words. It does not remove rare words from the vocabulary or corpus at all — rare words are essentially always kept, since their keep-probability is close to 1 under the standard formula. In fact, subsampling helps rare-word learning indirectly: by removing a huge share of "the", "of", "a" tokens from context windows, the remaining windows shift to contain relatively more rare and informative words as both centers and contexts, increasing the density of useful training signal for those rare words per unit of training time.
Is the dot product used for scoring the same as cosine similarity?
No, though they are related. SGNS scores pairs using the raw dot product , not the cosine similarity, which additionally normalizes by vector norms. During training this matters because the model can increase confidence in a positive pair either by aligning the vectors' directions or by simply growing their magnitudes, and in practice both effects occur to some extent. When embeddings are evaluated for word similarity or analogy tasks afterward, however, cosine similarity is almost universally used instead of raw dot product, since it discounts frequency-driven magnitude effects and better reflects semantic direction, a distinction relevant to later study of Embedding Geometry and Analogies.
How does negative sampling relate to ideas used outside NLP, like in recommendation systems?
The same reframing — expensive multi-class prediction over huge output spaces replaced by binary discrimination against sampled negatives — appears throughout machine learning wherever the "correct answer" must be chosen from an enormous set of candidates. Recommendation systems predicting which of millions of items a user will click use exactly this trick: sample a handful of non-clicked items as negatives rather than normalizing over the whole catalog. Retrieval-based question answering and dense passage retrieval systems do the same over document collections. This makes negative sampling one of the most widely reused computational tricks originating from Word2Vec, well beyond its original NLP context.
Can negative sampling be applied to CBOW as well as skip-gram?
Yes. In Continuous Bag-of-Words (CBOW), the model predicts a center word from the average (or sum) of its surrounding context word embeddings, rather than skip-gram's per-context-word prediction. Negative sampling applies identically: instead of a full softmax over the vocabulary to score the true center word against the averaged context vector, the model samples negative center words and trains a binary classifier the same way, using the same sigmoid-based objective and the same noise distribution. The gradient derivations are essentially identical, only the vector being scored (averaged context vs. single center) differs.