Skip-gram Model › Architecture: Two Embedding Matrices

Michael BrenndoerferApril 2, 20254 min read
Language AI HandbookAll chapters
Part 4 of 67Word Embeddings
Chapter 19Skip-gram Model › Architecture: Two Embedding Matrices
Reading section 3 of 14 · Architecture: Two Embedding Matrices · 4 minSection 3 of 14 · 4 min

Book contents

Section 3 of 14 · 4 min read

Skip-gram Model › Architecture: Two Embedding MatricesOne section · Sections in this chapter3 / 14 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

The Skip-gram architecture is a shallow neural network with one hidden layer and no nonlinear activation function. Its apparent simplicity is misleading, because all the meaningful computation happens in the weight matrices, not in any deep stacking of transformations.

The network contains three components:

  • Input layer: A one-hot vector of dimension VV (vocabulary size), with a 1 at the index of the center word and 0 everywhere else.
  • Hidden layer: A weight matrix W\mathbf{W} of shape V×dV \times d, where dd is the embedding dimension. Multiplying the one-hot input by W\mathbf{W} selects the dd-dimensional row corresponding to the center word.
  • Output layer: A second weight matrix W′\mathbf{W}' of shape d×Vd \times V that projects the hidden vector back to vocabulary size, producing a score for every word.

After training, we discard the output matrix and use W\mathbf{W} as our embedding lookup table. Each row of W\mathbf{W} is the embedding for the corresponding word.

The absence of a nonlinear activation function between the input embedding lookup and the output scoring is intentional. Adding nonlinearities would make the model harder to optimize and would not obviously improve the quality of the learned representations. The linear structure means the model is essentially learning a bilinear scoring function between center word embeddings and context word embeddings, and the geometry of that scoring function is what creates the useful structure in the embedding space.

Input and Output Representations

One-hot encoding gives each word a unique, orthogonal representation. Word ww with vocabulary index ii is represented as a vector x\mathbf{x} of length VV where xi=1x_i = 1 and all other entries are 0. This is not a meaningful representation on its own; its purpose is purely to select a row from the embedding matrix.

Multiplying a one-hot vector x\mathbf{x} by the embedding matrix W\mathbf{W} is equivalent to selecting row ii:

h=WTx=vwI\mathbf{h} = \mathbf{W}^T \mathbf{x} = \mathbf{v}_{w_I}

where:

  • h\mathbf{h}: the hidden layer vector of dimension dd, which is the center word embedding
  • W\mathbf{W}: the input embedding matrix of shape V×dV \times d
  • x\mathbf{x}: the one-hot input vector with a 1 at position ii
  • vwI\mathbf{v}_{w_I}: the ii-th row of W\mathbf{W}, the embedding for input word wIw_I

This selection operation is the key to Skip-gram's efficiency. We never multiply a full one-hot vector through a large matrix in practice. We simply look up a row. Because the one-hot vector is all zeros except at one position, the matrix multiplication collapses to a single row retrieval. Modern implementations store word embeddings in a dedicated Embedding lookup table, which is exactly this: a parameterized table where each row is a learnable vector, and integer indexing is used to retrieve the relevant row.

The output matrix W′\mathbf{W}' of shape d×Vd \times V computes a score for each vocabulary word. For context word wOw_O with vocabulary index jj, the score is:

uj=vwO′⋅hu_j = \mathbf{v}'_{w_O} \cdot \mathbf{h}

where:

  • uju_j: the unnormalized score (logit) for vocabulary word jj being a context word of wIw_I
  • vwO′\mathbf{v}'_{w_O}: the jj-th column of W′\mathbf{W}', the context embedding of word wOw_O
  • h\mathbf{h}: the center word embedding from the hidden layer

So every word has two vector representations: an input embedding (a row of W\mathbf{W}) used when the word is the center, and a context embedding (a column of W′\mathbf{W}') used when it appears in someone else's context window. This dual representation is a fundamental design feature of Word2Vec. After training, you typically use the input embeddings (W\mathbf{W}) as the final word vectors, though some practitioners average both matrices, or use the context embeddings for specific downstream tasks.

Why Two Matrices?

The use of separate input and context matrices deserves explanation, because it might seem redundant at first. Why should the embedding for "fox" as a center word differ from its embedding as a context word?

The reason is flexibility and symmetry breaking. If we used the same matrix for both roles, the model would be constrained to treat each word as both predictor and predicted in a symmetric way. With separate matrices, the model can learn that "fox" as a center word needs to be good at pointing toward animal-related words in context space, while "fox" as a context word needs to be pointed to by sentences that often contain fox-relevant contexts. These are related but not identical requirements, and separate matrices allow the model to satisfy them independently.

This also has an interesting geometric consequence. If you compute the dot product vwI⋅vwO′\mathbf{v}_{w_I} \cdot \mathbf{v}'_{w_O}, you are measuring how well word wIw_I as center predicts word wOw_O as context, which is not the same as asking whether wOw_O as center predicts wIw_I as context (that would be vwO⋅vwI′\mathbf{v}_{w_O} \cdot \mathbf{v}'_{w_I}). The model naturally handles asymmetric co-occurrence statistics this way.