Encoder-Decoder Framework › Encoder Architecture
Language AI HandbookAll chapters Encoder-Decoder Framework › Encoder ArchitectureOne section · Sections in this chapter4 / 16 ↓
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 encoder is the "reader" half of the system. Its job is to process an arbitrary-length input and distill it into a compact representation that the decoder can work from. Before diving into the mathematics, it helps to build intuition about what this compression process looks like.
Think of the encoder as a reader who is given a passage and asked to write a summary on a notecard of fixed size. After reading each sentence, the reader updates their mental model of what they have read so far. By the end of the passage, the notecard should contain everything important about the passage, but compressed into whatever fits. Early sentences may not make it onto the notecard if they were less important, or they may be represented implicitly through their effect on the reader's evolving understanding. This is exactly what the LSTM encoder does: its hidden state at each step is an evolving compressed summary, and the final state is the notecard passed to the decoder.
The encoder processes the source sequence and produces a sequence of hidden states . At each timestep , the encoder computes a new hidden state based on the current input token and the previous hidden state:
where:
- is the encoder hidden state at time
- is the embedding of the -th input token
- is the encoder recurrent cell (LSTM, GRU, or vanilla RNN)
- is the hidden size, a hyperparameter, typically 256 to 1024
After processing all input tokens, the context vector is taken as the final encoder hidden state:
where:
- is the context vector
- is the encoder hidden state after processing the last input token
For LSTM encoders, the encoder produces both a hidden state and a cell state , and both are passed to the decoder. This pair together forms the context.
The encoder starts with a zero hidden state and accumulates information about the input as it reads token by token from left to right. By the time it reaches the end of the sequence, the hidden state theoretically contains a summary of everything the encoder has seen. In practice, vanilla RNNs struggle to retain information from the beginning of long sequences due to vanishing gradients, which is why LSTMs and GRUs are preferred for the encoder.
Input Embeddings
Before the encoder processes any tokens, the source vocabulary must be mapped to dense vectors using an embedding layer. If the source vocabulary has size and we use embedding dimension , the embedding matrix maps each integer token index to a continuous vector. These embeddings are learned jointly with the rest of the model during training.
The encoder receives these embedded vectors as input at each timestep, not the raw integer indices. The embedding layer is a required component: it performs dimensionality reduction from a one-hot space of size (which may be 30,000 or more tokens) to a dense space of size (typically 128 to 512), and it learns to position semantically related words close together in that space. A word like "run" and "sprint" will end up with similar embeddings after training on parallel corpora, because they appear in similar translation contexts.
Embedding dimension and hidden dimension do not need to match, though they often do in practice. If they differ, a linear projection is typically inserted between the embedding layer and the recurrent cell to map the embedding into the recurrent input space.
Bidirectional Encoders
A standard encoder processes the input strictly left to right, meaning that the hidden state at position only incorporates information from tokens through . The hidden state at position therefore has the most information, but the hidden state at position 1 has almost none about the rest of the sequence. When we use only the final state as the context vector, we are relying on the LSTM's ability to remember all relevant early tokens, which degrades with sequence length.
Bidirectional encoders address this by running two separate recurrent layers over the input: one in the forward direction (left to right) and one in the backward direction (right to left). The forward layer produces states and the backward layer produces states . At each position, the two states are concatenated to give a full representation that incorporates context from both directions:
For the context vector in the basic encoder-decoder framework, we typically concatenate the final forward state and the initial (from the backward direction) backward state:
This gives the context vector access to the full forward pass summary and the full backward pass summary simultaneously. This provides a richer, more symmetric encoding of the source. In practice, bidirectional encoders consistently outperform unidirectional ones, especially for tasks where word order matters or where early tokens are important for understanding the sentence meaning.
The main cost of bidirectionality is that the context vector doubles in size (from to ), which means the decoder must also use hidden states of size , or a linear projection is needed to bring the context back to size before feeding it to the decoder.
Stacked Encoders
Just as we can stack LSTM layers in a standard RNN, we can stack them in the encoder. With layers, the first layer takes the embedded tokens as input, and each subsequent layer takes the hidden states of the layer below as input:
The final context vector is taken from the topmost layer: . In the Sutskever et al. 2014 paper, a 4-layer LSTM encoder with reversed source input was used, and the depth was an important contributor to the model's performance. Deep encoders can learn hierarchical representations: lower layers might capture syntactic structure while higher layers capture semantic content, analogous to how convolutional networks build from edge detectors to object detectors.
Deeper encoders require correspondingly deeper decoders with matching layer counts, and the hidden state from each encoder layer is used to initialize the corresponding decoder layer. This ensures that information at different levels of abstraction is properly propagated across the bottleneck.