ICS 582Lecture 04Part 07
Dense vectors and the skip-gram classifier
Why short dense vectors beat long sparse ones, the main ways to get them, and how word2vec turns embedding learning into a self-supervised binary task scored by the sigmoid of a dot product.
- Concepts
- 6
- Slides
- 61-74
- Reading
- 36 min
Why this part matters
This is where the lecture switches from counting to learning. Until now every vector was a row of a count table, reweighted by tf-idf or PPMI. From here on the vectors are parameters that a small classifier learns, and the classifier is trained on a task that running text answers for free. Skip-gram with negative sampling is an early, influential template for the pretext tasks that followed in NLP, including the masked-word objective of BERT, and it is a staple exam item: explain self-supervision, compute σ(c·w).
It also matters for research and real systems. The downloadable static vectors you will reach for (GoogleNews 300-d, GloVe 6B) and the gensim switches you will set (sg=1, negative=5, window=5) all come from the ideas below. The argument runs in six steps: why short dense vectors beat long sparse ones, where dense vectors come from, the idea of predicting instead of counting, how a window turns text into pairs, how a dot product becomes a probability, and how one window is scored as a whole. How the vectors are actually learned is the next part.
By the end you can
- Contrast sparse and dense vectors by length, zeros and value range, and give three reasons dense vectors help, including the car and automobile argument.
- Name the main sources of dense vectors (word2vec, GloVe, SVD/LSA, contextual models) and distinguish static from contextual embeddings.
- Explain self-supervision and the four-step skip-gram recipe, and say why the classifier is discarded while its weights are kept.
- Generate the positive (target, context) pairs for a ±m window, and relate m to the slides' L = 2m context words per target.
- Compute P(+|w,c) = σ(c·w) and P(-|w,c) = σ(-c·w) for given vectors.
- Score a whole window with the product of sigmoids and its log sum, and state the independence assumption behind it.
One sentence says "she drove the car to work"; another says "he parked the automobile outside". In a count space, drove collects weight on the car dimension and parked collects weight on the automobile dimension. Those are two different coordinates. If those are their only informative neighbors, the dot product of the two verbs is exactly 0, so their cosine is 0 too, even though any reader sees that the two sentences describe the same kind of event.
Worked example
Two verbs, two synonyms, zero similarity
Keep only the two relevant dimensions
Use the axes (car, automobile). drove = [1, 0] and parked = [0, 1].Dot product
1×0 + 0×1 = 0.Cosine
0 / (1 × 1) = 0. The vectors are orthogonal: as far as the space can tell, the two verbs share nothing.Result
Sparse vectors treat car and automobile as unrelated axes, so words that differ only in which synonym they co-occur with look completely dissimilar.
Part 03 previewed this contrast on slide 30; here it gets its full argument. The vectors of the last three parts were sparse vectors. Built from a tf-idf or Pointwise mutual information weighting, they have one dimension per vocabulary word, so their length is |V|, typically 20,000 to 50,000, and nearly every entry is zero. A Dense vector is the opposite on every count. It has a small fixed number of dimensions d, usually between 50 and 1000; almost all of its entries are non-zero; and they are real numbers that can be negative. The price is interpretability: the d dimensions do not correspond to context words or to anything else nameable (SLP 5.5). Such a vector is still an Embedding, just a learned one rather than a counted one.
| Property | Sparse (tf-idf, PPMI) | Dense (word2vec) |
|---|---|---|
| Length | |V| ≈ 20,000 to 50,000 | d ≈ 50 to 1000 |
| Zeros | Almost every entry | Almost none |
| Values | Counts or non-negative weights | Real numbers, positive or negative |
| Dimension meaning | Each axis is one context word | No clear interpretation |
| Weights a one-word classifier needs | 50,000 | 300 |
| Synonyms | Separate, orthogonal axes | Can share the same directions |
Three reasons dense vectors win
- Fewer weights to learn. A classifier that uses one word as a feature needs one weight per dimension: 300 weights for a dense vector instead of 50,000 for a sparse one. Fewer parameters may generalize better and overfit less.
- Better Synonymy. In a dense space, car and automobile can occupy nearby directions, so a word whose neighbors include car is automatically close to a word whose neighbors include automobile. The Cosine similarity of drove and parked is no longer forced to zero.
- Empirically better. SLP states it bluntly: dense vectors work better in every NLP task than sparse vectors. The slide says the same more cautiously: in practice, they work better.
Recall
Why do sparse vectors fail on car and automobile, and give two other reasons dense vectors help.
Quick check
One word occurs only near car, another only near automobile. What cosine do their sparse count vectors give?
Suppose you need word vectors for a project tomorrow. You do not have to train anything. You can download the word2vec GoogleNews vectors, or one of the GloVe sets from Stanford, and have a dense vector for millions of words in a few minutes. Knowing where each set comes from tells you what it can and cannot do.
Pretrained static vectors you can download today
- word2vec GoogleNews
- 300-d vectors for 3,000,000 words and phrases, trained on part of Google News (about 100 billion words); 1,662 MB as word2vec-google-news-300 in gensim-data
- GloVe 6B
- Wikipedia 2014 plus Gigaword 5, 400K vocabulary, in 50, 100, 200 and 300 dimensions
- GloVe, larger sets
- Common Crawl (42B and 840B tokens), Twitter (27B), and newer 2024 Dolma and Wikipedia plus Gigaword releases
The lecture sorts dense vectors into three families. The first is inspired by neural language models: learn vectors by predicting words from their neighbors. Word2vec is the flagship, and it is a toolkit with two algorithms, Skip-gram (predict the neighbors from the word) and Continuous bag of words (predict the word from its neighbors). The slide also places GloVe here, which is a simplification noted below. The second family is factorization: take a count matrix and compress it with singular value decomposition. Latent semantic analysis (LSA) is SVD applied to a term-document matrix with the first 300 or so dimensions kept (Deerwester et al. 1990, in SLP's history section). The slide then presents contextual models such as ELMo and BERT as an alternative to these static embeddings. Both the SVD bullet and the contextual bullet are greyed out, because this lecture concentrates on word2vec.
| Family | Example | Learns from | One vector per |
|---|---|---|---|
| Prediction (neural-LM inspired) | word2vec SGNS, CBOW | Local windows, by predicting neighbors | Word type |
| Global co-occurrence regression | GloVe | Global co-occurrence counts | Word type |
| Matrix factorization | SVD, LSA | Term-document (or PPMI) matrix | Word type |
| Contextual | ELMo, BERT | The whole sentence, at run time | Token in context |
The last column is the line that matters most. Word2vec, GloVe and LSA all produce a Static embedding: one fixed vector per word type, looked up from a table. The word bank gets the same vector in "river bank" and "bank loan", so Polysemy is averaged into a single point. A Contextual embedding is computed by running the whole sentence through a network, so each token occurrence gets its own vector (Peters et al. 2018; Devlin et al. 2019). Those models come later in the course; this lecture is about static vectors.
In practice you train your own vectors with gensim. Its defaults are worth memorizing because they bite: vector_size=100, window=5, negative=5 (the docs say usually between 5 and 20), ns_exponent=0.75, min_count=5, and sg=0, which means CBOW.
from gensim.models import Word2Vec
import gensim.downloader as api
model = Word2Vec(
sentences=corpus,
vector_size=300,
window=5,
sg=1,
negative=5,
min_count=5,
)
google_news = api.load("word2vec-google-news-300")
google_news.most_similar("automobile", topn=3)Recall
Static versus contextual embeddings: give one example of each.
Read the phrase "...a tablespoon of apricot jam...". Without anyone annotating anything, it hands you a labeled fact: (apricot, jam) is a yes, these two words occur near each other. Now pick a random word from the lexicon, say aardvark. (apricot, aardvark) is almost certainly a no. Every sentence of every book and web page produces such facts by the dozen.
That is the whole idea behind Skip-gram with negative sampling. Instead of counting how often a word c occurs near apricot, train a binary classifier on the question "is c likely to show up near apricot?" Nobody actually cares about that question. What we keep are the weights the classifier learns in order to answer it, and those weights are the embeddings. Because the gold answers come from running text rather than from people, this is Self-supervision.
The four-step recipe
- Treat the target word and each neighboring context word as a positive example.
- Randomly sample other words from the lexicon to make negative examples.
- Train logistic regression to tell the two kinds of pair apart.
- Throw the classifier away and use its learned weights as the embeddings.
The idea has a lineage. Bengio et al. (2003) and Collobert et al. (2011) had already shown that the next word in running text is a free supervision signal for learning word vectors, and Collobert et al. stressed the "vast amounts of mostly unlabeled training data" this unlocks. Word2vec simplifies their neural language models in two ways (SLP 5.5). It replaces the hard task of predicting the next word over the whole vocabulary with a yes-or-no question about a single pair, and it replaces a multi-layer network with plain logistic regression. The payoff was speed: Mikolov et al. (2013a) learned high quality vectors from a 1.6 billion word data set in less than a day.
The binary framing is also what keeps training cheap. The basic skip-gram formulation defines its probability with a softmax over the whole vocabulary, whose cost grows with W, "often large (10^5 to 10^7 terms)" (Mikolov et al. 2013b). Negative sampling replaces that sum with a handful of k sampled noise words, 5 to 20 for small data sets and 2 to 5 for large ones. How those negatives are drawn and how the weights are updated is the subject of the next part.
Recall
What is self-supervision in word2vec, and why does it need no human labels?
Recall
List the four steps of the skip-gram intuition.
Quick check
In skip-gram training, where do the gold labels come from?
Take the running text "...lemon, a tablespoon of apricot jam, a pinch..." and put a window of two words on each side of apricot. The target is w = apricot, and the four context words are c1 = tablespoon, c2 = of, c3 = jam and c4 = a. Each one forms a positive training pair with the target.
Worked example
Positive pairs from a ±2 window
Target apricot
(apricot, tablespoon), (apricot, of), (apricot, jam), (apricot, a).Slide one word to the right: target jam
(jam, of), (jam, apricot), (jam, a), (jam, pinch).Result
Every token takes a turn as the target. A window of ±2 gives up to 4 positive pairs per target, and in general a half-width of m gives up to 2m. Fewer appear only at the edges of a text.
A note on letters: the slides and SLP write L for the number of context words being scored, so a ±2 window has L = 4. Keep that in mind when you meet c_1:L in the last concept of this part. The half-width is written m throughout this lecture, so L = 2m. Try the window yourself: click any word to make it the target and change the half-width.
- (apricot, tablespoon)
- (apricot, of)
- (apricot, jam)
- (apricot, a)
Once the pairs exist, the classifier's job is simple to state. Given a candidate pair (w, c), return the probability that c is a real context word of w. For (apricot, jam) that probability should be high; for (apricot, aardvark) it should be low. Since there are only two outcomes, the probability of the negative answer is whatever is left over:
Recall
How many positive pairs does a ±3 window give for a target in mid-sentence, and what is the slides' L for it?
Quick check
With a ±1 window over '...tablespoon of apricot jam, a pinch...', which positive pairs does target jam produce?
Give apricot a toy three-dimensional vector w = (1, 0.5, -1). Give jam the context vector c = (2, 1, -0.5) and aardvark c = (-1, 0.5, 1). Multiply apricot by jam elementwise and add: 2 + 0.5 + 0.5 = 3. Do the same with aardvark: -1 + 0.25 - 1 = -1.75. The real neighbor scores high, the random word scores low. The question is how to turn those two scores into probabilities.
The intuition the classifier uses is the one from the cosine parts: two vectors are similar when their Dot product is high, and the Cosine similarity is just a dot product divided by the two vector lengths. So skip-gram takes the dot product c·w as its similarity score. But neither a dot product nor a cosine is a probability. Because embedding entries can be negative, the dot product can be anything from -∞ to ∞ (SLP 5.5.1).
Logistic regression already has the fix. The sigmoid function maps any real number into the open interval (0, 1), so the classifier passes the dot product through it:
The identity 1 - σ(x) = σ(-x) is worth checking once, because it is used constantly: the two cases always sum to 1, and flipping the sign of the score swaps them. A few anchor values make hand computation quick: σ(0) = 0.5, σ(2) = 0.8808, σ(-2) = 0.1192, σ(5) = 0.9933, σ(-5) = 0.0067.
Worked example
P(+) for jam and for aardvark, with w = (1, 0.5, -1)
Multiply elementwise
jam: (1×2, 0.5×1, -1×-0.5) = (2, 0.5, 0.5). aardvark: (1×-1, 0.5×0.5, -1×1) = (-1, 0.25, -1).Sum
c·w = 3 for jam and c·w = -1.75 for aardvark.Exponentiate the negated score
e^-3 = 0.0498 and e^1.75 = 5.7546.Invert one plus that
jam: 1 / 1.0498 = 0.9526. aardvark: 1 / 6.7546 = 0.1480.Result
P(+ | apricot, jam) = 0.9526 and P(+ | apricot, aardvark) = 0.1480, so P(- | apricot, aardvark) = 0.8520.
Recall
Compute P(+|w,c) for w = (1, 0.5, -1) and c = (2, 1, -0.5).
Quick check
With w = (1, 0.5, -1) and c = (2, 1, -0.5), what is P(+|w,c)?
One pair at a time is not enough: apricot has four neighbors in its ±2 window, and the classifier should score the whole window. Keep w = (1, 0.5, -1) and give each of the four context words a toy vector.
| Context | c | c·w | σ(c·w) | log σ |
|---|---|---|---|---|
| tablespoon | (0.5, 0, -0.5) | 1.0 | 0.7311 | -0.3133 |
| of | (0.2, -0.4, 0.1) | -0.1 | 0.4750 | -0.7444 |
| jam | (2, 1, -0.5) | 3.0 | 0.9526 | -0.0486 |
| a | (0, 0.2, 0) | 0.1 | 0.5250 | -0.6444 |
Skip-gram makes one simplifying move: it assumes the context words are independent of each other given the target. Under that assumption the probability that all of them are real neighbors is the product of the individual sigmoid probabilities, and its logarithm is a sum.
Worked example
Product and log sum for the apricot window
Multiply the four sigmoids
0.7311 × 0.4750 × 0.9526 × 0.5250 = 0.1737.Add the four logs
-0.3133 - 0.7444 - 0.0486 - 0.6444 ≈ -1.7507.Check they agree
e^-1.7507 ≈ 0.1737. The log sum is the log of the product.Result
Four true neighbors give a joint probability of only 0.1737, dragged down by the weakly scored function words of and a. With hundreds of factors the product would underflow, which is why training works in log space.
That last sentence hides a detail that sets up the next part. SLP's figure 5.6 shows that skip-gram stores two embeddings per word: one for when the word is a target and one for when it is a context. They live in a target matrix W and a context matrix C, the Target and context matrices, so the parameters are 2|V| vectors of dimension d. Learning those two matrices from positive and negative pairs is what part 8 is about.
Recall
Write P(+|w,c_1:L), say which assumption it relies on, and why we take logs.
Quick check
Why does skip-gram multiply the sigmoid scores of the context words?
Recap
If you remember nothing else
- Sparse tf-idf and PPMI vectors have length |V| (20,000 to 50,000) and are mostly zeros. Dense embeddings have 50 to 1000 dimensions with real values that can be negative.
- Dense vectors need far fewer classifier weights (300 vs 50,000), capture synonymy that separate dimensions miss (car and automobile), and work better in practice.
- The dense families are word2vec (skip-gram, CBOW), GloVe (global co-occurrence), SVD/LSA, and contextual models (ELMo, BERT). The first three are static: one vector per word type.
- Word2vec predicts rather than counts. A binary classifier asks "is c near w?", and its learned weights become the embeddings.
- Self-supervision: neighbors in running text are the gold positives and random lexicon words are the negatives, so no human labels are needed.
- A ±2 window around apricot gives four positives: tablespoon, of, jam, a.
- P(+|w,c) = σ(c·w) = 1/(1 + e^(-c·w)) and P(-|w,c) = σ(-c·w). σ(0) = 0.5.
- Assuming independent context words, P(+|w,c_1:L) = ∏σ(c_i·w) and log P = Σ log σ(c_i·w).
- SGNS stores two vectors per word: a target matrix W and a context matrix C.
Sources
- Speech and Language Processing, chapter 5: Embeddings, section 5.5 Word2vecBookJurafsky and Martin, draft of August 2026Dense versus sparse, the 300 vs 50,000 weights, car and automobile, self-supervision and the four steps, eqs 5.11 to 5.18, the -∞ to ∞ remark, and figure 5.6 with W and C(opens in a new tab)
- Efficient Estimation of Word Representations in Vector SpacePaperMikolov, Chen, Corrado and Dean, arXiv 2013CBOW and skip-gram; high quality vectors from 1.6 billion words in less than a day(opens in a new tab)
- Distributed Representations of Words and Phrases and their CompositionalityPaperMikolov, Sutskever, Chen, Corrado and Dean, NIPS 2013Negative sampling, k of 5 to 20 or 2 to 5, softmax cost of 10^5 to 10^7 terms, subsampling(opens in a new tab)
- GloVe: Global Vectors for Word RepresentationPaperPennington, Socher and Manning, EMNLP 2014(opens in a new tab)
- GloVe project pageDocsStanford NLPPretrained sets: 6B, 42B, 840B, Twitter, and the 2024 releases(opens in a new tab)
- word2vec project archiveDocsGoogle Code ArchiveGoogleNews vectors: 300-d, 3 million words and phrases, about 100 billion words(opens in a new tab)
- gensim Word2Vec documentationDocsgensimDefaults vector_size=100, window=5, sg=0 (CBOW), negative=5, ns_exponent=0.75, min_count=5(opens in a new tab)
- gensim-data model catalogueDocsGitHub (piskvorky)word2vec-google-news-300: 3,000,000 vectors, 1,662 MB(opens in a new tab)
- Don't count, predict! A systematic comparison of context-counting vs. context-predicting semantic vectorsPaperBaroni, Dinu and Kruszewski, ACL 2014(opens in a new tab)
- Improving Distributional Similarity with Lessons Learned from Word EmbeddingsPaperLevy, Goldberg and Dagan, TACL 2015(opens in a new tab)
- Neural Word Embedding as Implicit Matrix FactorizationPaperLevy and Goldberg, NIPS 2014(opens in a new tab)
- A Neural Probabilistic Language ModelPaperBengio, Ducharme, Vincent and Jauvin, JMLR 2003(opens in a new tab)
- Natural Language Processing (Almost) from ScratchPaperCollobert et al., JMLR 2011(opens in a new tab)
- Deep Contextualized Word Representations (ELMo)PaperPeters et al., NAACL 2018(opens in a new tab)
- BERT: Pre-training of Deep Bidirectional Transformers for Language UnderstandingPaperDevlin et al., NAACL 2019(opens in a new tab)