Part of Language AI Handbook
GPT-1 paired generative pretraining with task-specific fine-tuning. Covers its architecture, objective, benchmark results, and role in transfer learning.
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
GPT-1
In June 2018, OpenAI released a paper titled "Improving Language Understanding by Generative Pre-Training." The model it introduced, later known as GPT-1, wasn't the largest language model of its time, nor did it immediately dominate benchmarks. But it showed that a simple recipe of unsupervised pre-training on raw text followed by supervised fine-tuning could achieve state-of-the-art results across diverse NLP tasks. This "pre-train then fine-tune" approach would become the dominant paradigm for natural language processing, reshaping how the entire field thought about model development.
GPT-1 arrived as the field was changing. Researchers knew that language models trained on large corpora learn useful representations, but the common view held that task-specific architectures were necessary for each downstream application. If you wanted to classify sentiment, you built a sentiment classifier. If you wanted to detect entailment, you designed an entailment model. Every new task required designing a new system from scratch, curating labeled data, and training it end-to-end. GPT-1 challenged this assumption. By using a single, unified transformer decoder architecture for both pre-training and fine-tuning, it showed that generative pre-training creates representations detailed enough to transfer to classification and similarity tasks, as well as entailment and question answering, with minimal architectural changes.
Think of GPT-1's pre-training as building a powerful general-purpose language engine. Just as a car engine can power vehicles of many different designs, the pre-trained transformer provides a shared foundation that can be adapted to many different downstream tasks. You don't build a new engine for each car model: you refine an existing one. GPT-1 extended this logic to language: don't build a new model for each NLP task, pre-train a shared representation and adapt it through fine-tuning.
The model was trained on the BooksCorpus dataset, roughly 800 million words spanning thousands of unpublished novels across genres. This raw, unlabeled text provided a rich training signal without any human annotation. The key insight behind the approach was that predicting the next word in a novel requires deep language understanding: you need to track characters across chapters, understand discourse coherence, resolve ambiguous pronoun references, and reason about causal and temporal relations. A model forced to predict narrative text reliably will, in the process, develop broadly useful linguistic representations.
What made GPT-1 particularly significant was its architectural simplicity. The model used a decoder-only transformer, a straightforward stack of self-attention layers with causal masking, applied uniformly at both pre-training and fine-tuning time. There were no task-specific components, no complex multi-task training objectives, and no elaborate engineering. The simple recipe was easy to reproduce and extend to larger models. This last property would prove decisive: GPT-2, GPT-3, and their successors all follow the same fundamental design, simply larger.
This chapter explores the GPT-1 architecture in detail. We'll examine its decoder-only design, understand the pre-training objective and data, walk through the fine-tuning approach that enabled transfer learning, and assess the model's impact on the trajectory of NLP research. Along the way, we'll implement the core components in PyTorch to build concrete intuition for how the system works from the ground up.
GPT-1 was published in June 2018, just four months before BERT (October 2018). The two models represent two competing design philosophies that shaped NLP for years. GPT-1 used a decoder-only architecture with a left-to-right (causal) language modeling objective, which is well-suited to text generation and can be scaled to long sequences. BERT used an encoder-only architecture with a masked language modeling objective. This produces bidirectional representations better suited to understanding tasks. In the short term, BERT's bidirectional approach dominated benchmarks for classification and entailment tasks. Over the long term, the GPT lineage won out: GPT-3, GPT-4, and virtually all modern large language models use decoder-only architectures, validating the scalability of GPT-1's original design choice. ELMo, released in early 2018, was a contemporary using bidirectional LSTMs, and also demonstrated the value of pre-trained language representations. This provides important validation for the general approach before the GPT and BERT era.
The Architecture
GPT-1 uses a decoder-only transformer architecture, a design choice that distinguished it from contemporary models like ELMo (which used bidirectional LSTMs) and from the later BERT (which used bidirectional transformer encoders). The decoder-only choice wasn't arbitrary: it enabled a simple, scalable pre-training objective based on next-token prediction. With a decoder-only architecture, the model processes text from left to right, predicting each token given all preceding tokens. This autoregressive structure means training is straightforward: run the sequence through the model, compute the probability of each token given its prefix, and minimize the cross-entropy loss. No special masking schemes, no separate encoder-decoder coupling, and no architectural asymmetry between training and inference.
The choice to use a decoder-only design, rather than a full encoder-decoder architecture like the original transformer from Vaswani et al. (2017), was deliberate. The encoder-decoder architecture excels at sequence-to-sequence tasks like translation, where the input and output have different structures. But GPT-1 aimed at language understanding tasks where the input is a text sequence and the output is a label or classification decision. A single unified decoder, applied to the reformatted input sequence, is simpler, requires fewer parameters for a given depth, and removes the architectural asymmetry that makes encoder-decoder models harder to scale uniformly. The key insight is that if you can reformulate all tasks as text sequences, you don't need the full encoder-decoder complexity.
The depth of the architecture reflects GPT-1's position as one of the first large transformer language models. At 12 layers, 768 hidden dimensions, and 12 attention heads, the model follows the same configuration that would later be used for BERT-Base. This allows direct architectural comparisons between the two approaches. Each attention head operates over a 64-dimensional subspace of the hidden representation (768 / 12 = 64), which provides enough capacity for different heads to specialize in different types of relationships. The four-fold expansion in the feed-forward network (768 to 3072 hidden dimensions) follows the convention established in the original transformer paper. This provides a bottleneck structure where the model can learn complex non-linear transformations of the attention output.
Understanding why these design choices work requires thinking about what the model needs to do during pre-training. At each position, the model reads all preceding tokens and must predict the most likely next token from a vocabulary of 40,000 subwords. Getting this right requires recognizing syntactic patterns, tracking semantic entities across long spans, resolving anaphora, and modeling discourse structure. Twelve layers of self-attention provide enough depth to compose these different types of information progressively, with early layers capturing local syntactic patterns and later layers capturing longer-range semantic and discourse relationships.
GPT-1 consists of 12 transformer decoder layers with 12 attention heads each, a hidden dimension of 768, and a context window of 512 tokens. The model contains approximately 117 million parameters.
The architectural specifications are:
| Parameter | Value |
|---|---|
| Layers | 12 |
| Hidden size () | 768 |
| Attention heads | 12 |
| Head dimension | 64 |
| Feed-forward size | 3072 |
| Context window | 512 tokens |
| Vocabulary size | 40,000 (BPE) |
| Parameters | ~117M |
These numbers match BERT-Base closely (which also has 12 layers, 768 hidden dimensions, and 12 heads), enabling direct comparisons. The key architectural difference lies in the attention pattern: GPT-1 uses causal masking where each position can only attend to previous positions, while BERT uses bidirectional attention where each position attends to the full sequence.
Transformer Decoder Stack
Each layer in GPT-1 follows the standard transformer decoder block pattern. The input passes through masked multi-head self-attention, then a position-wise feed-forward network, with residual connections and layer normalization around each sublayer. The residual connections are important: they allow gradient to flow directly back through the network without passing through the attention and feed-forward operations, which prevents the vanishing gradient problem that would otherwise make deep networks difficult to train. Layer normalization stabilizes the activations at each sublayer. This keeps the signal entering each layer has consistent scale regardless of the scale of the gradients produced by training. Together, these two techniques allow GPT-1 to be trained to depths that would have been impractical with earlier architectures.
The GPT-1 paper uses post-normalization (LayerNorm applied after the residual addition), which was the convention inherited from the original transformer. Later models, including GPT-2 and GPT-3, switched to pre-normalization (LayerNorm applied to the input before attention and feed-forward), which provides more stable training at larger scales. This seemingly minor architectural detail turns out to matter significantly at scale: pre-normalization smooths optimization, allowing higher learning rates and more reliable training convergence for very deep or very wide models.
import torch.nn as nn
class GPT1Layer(nn.Module):
"""Single transformer decoder layer as used in GPT-1."""
def __init__(
self,
hidden_size: int = 768,
num_heads: int = 12,
intermediate_size: int = 3072,
dropout: float = 0.1,
):
super().__init__()
self.attention = nn.MultiheadAttention(
embed_dim=hidden_size,
num_heads=num_heads,
dropout=dropout,
batch_first=True,
)
self.feed_forward = nn.Sequential(
nn.Linear(hidden_size, intermediate_size),
nn.GELU(),
nn.Linear(intermediate_size, hidden_size),
nn.Dropout(dropout),
)
self.norm1 = nn.LayerNorm(hidden_size)
self.norm2 = nn.LayerNorm(hidden_size)
self.dropout = nn.Dropout(dropout)
def forward(
self,
x: torch.Tensor,
attn_mask: torch.Tensor | None = None,
) -> torch.Tensor:
# Self-attention with residual (post-norm)
attn_out, _ = self.attention(x, x, x, attn_mask=attn_mask)
x = self.norm1(x + self.dropout(attn_out))
# Feed-forward with residual (post-norm)
ff_out = self.feed_forward(x)
x = self.norm2(x + ff_out)
return xGPT-1 uses GELU activation in the feed-forward network rather than ReLU. GELU provides a smoother non-linearity that empirically improves training dynamics in transformer models. The activation function multiplies each input value by the probability that a standard normal random variable would be less than that value:
where:
- : the input value to the activation function
- : the cumulative distribution function (CDF) of the standard normal distribution, which gives the probability that a standard Gaussian random variable is less than
- : the output, which smoothly transitions between suppressing small/negative values and passing large positive values
This formulation creates a smooth gating effect. For large positive , , so the output is approximately . For large negative , , so the output is approximately 0. Unlike ReLU's hard cutoff at zero, GELU provides a gradual transition that can improve gradient flow during training.

Input Representation
GPT-1's input representation combines token embeddings with learned position embeddings. Unlike the sinusoidal positional encodings from the original transformer paper, GPT-1 learns position embeddings during training. This allows the model to discover position-specific patterns relevant to its training data. Sinusoidal embeddings follow a fixed mathematical formula based on sine and cosine functions of position and dimension indices, which ensures that the model can generalize to positions it hasn't seen during training. Learned embeddings, by contrast, are just parameters initialized randomly and updated via gradient descent, which means they can specialize to the position-dependent patterns in the training data but cannot necessarily generalize to positions outside the training context window.
The decision to use learned rather than sinusoidal position embeddings was motivated by empirical performance rather than theoretical considerations. In practice, for sequences within the training context length, learned embeddings typically match or slightly outperform sinusoidal embeddings. The key practical constraint is that learned embeddings are strictly limited to the training context length: GPT-1 trained on sequences up to 512 tokens cannot use position embeddings for positions beyond 512, while sinusoidal embeddings could in principle be applied to arbitrarily long sequences. This became a significant architectural constraint as the field moved toward longer-context models.
The token embeddings themselves are 768-dimensional vectors, one per entry in the 40,000-token BPE vocabulary. These embeddings are initialized randomly and trained end-to-end alongside all other model parameters. After pre-training, these embeddings encode rich semantic and syntactic information about each token's typical linguistic context, capturing relationships that go far beyond simple word similarity. The position embeddings add a second 768-dimensional vector that encodes where in the sequence a token appears, allowing the model to distinguish between "the cat chased the dog" and "the dog chased the cat" even though both contain the same tokens in a bag-of-words representation.
class GPT1Embeddings(nn.Module):
"""Token and position embeddings for GPT-1."""
def __init__(
self,
vocab_size: int = 40000,
hidden_size: int = 768,
max_positions: int = 512,
dropout: float = 0.1,
):
super().__init__()
self.token_embeddings = nn.Embedding(vocab_size, hidden_size)
self.position_embeddings = nn.Embedding(max_positions, hidden_size)
self.dropout = nn.Dropout(dropout)
# Register position indices as buffer
self.register_buffer(
"position_ids", torch.arange(max_positions).unsqueeze(0)
)
def forward(self, input_ids: torch.Tensor) -> torch.Tensor:
seq_len = input_ids.size(1)
position_ids = self.position_ids[:, :seq_len]
token_emb = self.token_embeddings(input_ids)
position_emb = self.position_embeddings(position_ids)
embeddings = token_emb + position_emb
return self.dropout(embeddings)Input shape: torch.Size([2, 10]) Output shape: torch.Size([2, 10, 768]) Embedding dimension: 768
The embedding layer turns input token IDs into 768-dimensional vectors. Adding position embeddings directly to token embeddings (rather than concatenating) keeps the hidden dimension constant throughout the network. This matches the original transformer design.



Causal Masking
The defining characteristic of GPT-1's decoder architecture is causal masking. During the forward pass, each token can only attend to tokens at earlier positions in the sequence. This constraint ensures that the model cannot "cheat" by looking at future tokens when predicting the next token. Think of it as the difference between reading a sentence left to right, word by word, versus reading the whole sentence and then predicting what each word "should be." The causal constraint forces the model to develop predictive representations based only on information it would realistically have access to at each position.
Without causal masking, a language model could trivially achieve perfect next-token prediction training accuracy by simply looking at the token it is supposed to predict. The mask prevents this shortcut. Every position must base its prediction purely on left context, forcing the model to learn the statistical regularities of language rather than memorizing a lookup table. This is implemented as a simple upper-triangular mask applied to the attention score matrix before the softmax: positions in the upper triangle are set to negative infinity, which causes softmax to assign them exactly zero attention weight.
The causal constraint has an important consequence for how information flows through the model. At position , the attention mechanism can gather information from any subset of positions , weighting each by relevance. This means that the model can perform long-range lookups, attending back to relevant words far earlier in the sequence, without violating the causal ordering. The multi-head structure allows different heads to perform different lookup strategies simultaneously: one head might specialize in recent context, another in syntactic dependencies, and another in thematic coherence across the full available history.
def create_causal_mask(seq_len: int) -> torch.Tensor:
"""
Create a causal attention mask.
Returns a mask where True indicates positions to block.
"""
mask = torch.triu(torch.ones(seq_len, seq_len), diagonal=1)
return mask.bool()
The triangular pattern shows that position 0 can only attend to itself, position 1 can attend to positions 0 and 1, and so on. Position 7 (the last position) can attend to all positions. This asymmetry means that later positions have access to more context, which is why language models typically generate text from left to right.

Complete Model Architecture
Assembling the components, the complete GPT-1 architecture stacks 12 decoder layers between the embedding layer and a final language modeling head. The flow through the model is: input token IDs go through the combined token and position embedding layer to produce a sequence of 768-dimensional vectors; these pass through 12 transformer decoder layers, each applying causal self-attention followed by a feed-forward network with residual connections and layer normalization; the output of the final decoder layer passes through a final layer normalization; and the resulting representations are projected to vocabulary logits via the weight-tied output matrix. The architecture is entirely sequential in the depth dimension (layer 2 can only run after layer 1 finishes) but parallel within each layer (all positions in the sequence are processed simultaneously).
Weight tying is an important detail worth understanding. The output projection layer (which maps the 768-dimensional hidden state to 40,000 vocabulary logits) uses the same weight matrix as the input token embeddings, but transposed. This means the model learns a single 40,000 × 768 matrix that is used both to map token IDs to embeddings at the input and to map hidden states back to vocabulary scores at the output. The justification is that the input and output embedding spaces should be coherent: if "cat" has a certain embedding as input, then the model should also assign a high score to "cat" at the output when its hidden state is similar to the "cat" embedding. Weight tying enforces this coherence structurally and has been consistently shown to improve performance across language model architectures.
class GPT1Model(nn.Module):
"""Complete GPT-1 architecture."""
def __init__(
self,
vocab_size: int = 40000,
hidden_size: int = 768,
num_layers: int = 12,
num_heads: int = 12,
intermediate_size: int = 3072,
max_positions: int = 512,
dropout: float = 0.1,
):
super().__init__()
self.embeddings = GPT1Embeddings(
vocab_size, hidden_size, max_positions, dropout
)
self.layers = nn.ModuleList(
[
GPT1Layer(hidden_size, num_heads, intermediate_size, dropout)
for _ in range(num_layers)
]
)
self.ln_f = nn.LayerNorm(hidden_size)
self.lm_head = nn.Linear(hidden_size, vocab_size, bias=False)
# Weight tying: share embeddings with output projection
self.lm_head.weight = self.embeddings.token_embeddings.weight
def forward(
self,
input_ids: torch.Tensor,
return_hidden_states: bool = False,
) -> dict[str, torch.Tensor]:
seq_len = input_ids.size(1)
attn_mask = create_causal_mask(seq_len).to(input_ids.device)
hidden_states = self.embeddings(input_ids)
all_hidden_states = [hidden_states] if return_hidden_states else None
for layer in self.layers:
hidden_states = layer(hidden_states, attn_mask)
if return_hidden_states:
all_hidden_states.append(hidden_states)
hidden_states = self.ln_f(hidden_states)
logits = self.lm_head(hidden_states)
output = {"logits": logits, "last_hidden_state": hidden_states}
if return_hidden_states:
output["hidden_states"] = all_hidden_states
return outputTotal parameters: 116,169,216 Input shape: torch.Size([2, 32]) Logits shape: torch.Size([2, 32, 40000]) Hidden state shape: torch.Size([2, 32, 768])
The model contains approximately 117 million parameters. Note the weight tying between the input token embeddings and the output projection layer (lm_head). This technique reduces parameters by about 30 million (40,000 vocabulary × 768 dimensions) and has been shown to improve performance by enforcing consistency between how tokens are represented at input and predicted at output.

Worked Example: Forward Pass Through a Tiny GPT
Before diving into pre-training, let's trace a concrete forward pass through a minimal GPT-1-like model to build intuition for how information flows. We'll use a tiny 2-layer model with 4-dimensional embeddings and a vocabulary of 6 tokens, small enough to reason about numerically.
Suppose our vocabulary is {the, cat, sat, on, mat, [EOS]} with token IDs 0 through 5. Our input is the sequence [the, cat, sat], corresponding to token IDs [0, 1, 2].
Step 1: Token and Position Embedding Lookup. We look up the 4-dimensional embedding vector for each token, and the 4-dimensional position embedding for each position, then add them:
where is the token ID at position . Say the result is:
Step 2: Causal Self-Attention (Layer 1). We compute queries , keys , and values where is the matrix of input embeddings. The attention scores are:
where (the head dimension). We then apply the causal mask: positions where are set to before the softmax, so that token only attends to positions through . After softmax, the attention weights for position 2 ("sat") might look like with . The output for position 2 is the weighted sum , which blends information from "the", "cat", and "sat" according to their relevance.
Step 3: Feed-Forward Network. The attention output passes through a two-layer feed-forward network with GELU activation. For a hidden dimension of 16 (4x expansion), this computes:
Each token is processed independently by the FFN, allowing the model to apply a non-linear transformation to each position's representation after the attention aggregation step.
Step 4: Repeat for Layer 2. The output of Layer 1 becomes the input to Layer 2, which applies another round of causal self-attention and feed-forward processing. After 2 layers, we apply a final LayerNorm and multiply by the weight-tied output matrix (which is the transpose of the token embedding matrix) to get logits over the vocabulary.
Step 5: Compute Loss. The model's logit vector at position 0 is used to predict the token at position 1 ("cat"), the logit vector at position 1 predicts position 2 ("sat"), and the logit vector at position 2 predicts the next token ("on", ID=3). We apply softmax to each logit vector and compute cross-entropy against the correct targets. The total loss is the average of these three per-position losses. Backpropagation then updates all parameters to increase the probability of the correct continuations.
The key insight from this trace is that the model performs next-token predictions simultaneously in a single forward pass. This efficiency, called teacher forcing, is why autoregressive language models train much faster than they might seem: every token in every training sequence contributes a training signal.
Pre-Training Objective
GPT-1's pre-training objective is straightforward: predict the next token given all previous tokens. This is the standard language modeling objective, also called causal language modeling or autoregressive language modeling. Its elegance lies in how much linguistic knowledge it implicitly requires. To predict the next word in a sentence, the model must understand syntax (subject-verb agreement, grammatical case), semantics (word meaning and contextual sense), discourse (what the passage is about, what entities are in play), and pragmatics (what continuation would be coherent given the genre and register of the text). No single one of these abilities is directly trained: they all emerge as instrumental to the core prediction task.
The language modeling objective also provides very dense training signal. For a sequence of tokens, the model makes predictions during the forward pass (each position predicts its successor). This means every token in every training example contributes gradient information to every forward pass. Compare this to supervised learning approaches that might have a single label for an entire document: GPT-1's pre-training extracts far more signal from each training example, making efficient use of the BooksCorpus data.
Another important property of the language modeling objective is its generality. Unlike masked language modeling (used in BERT), which requires specific masking strategies and produces a model optimized for filling in blanks, causal language modeling produces a model optimized for sequentially generating or continuing text. This generality is part of why the GPT architecture scaled so effectively: the training objective remained valid and informative regardless of how large the model became or how much data it trained on. There was no need to change the training procedure as the model grew from 117M to 1.5B to 175B parameters.
Given a sequence of tokens , the model learns to maximize the likelihood of each token given its prefix: .
For a sequence of tokens , the pre-training objective is to maximize:
where:
- : the language modeling loss function (log-likelihood to maximize)
- : the input sequence of tokens
- : the token at position
- : the probability of token given all preceding tokens, parameterized by model weights
- : all learnable parameters of the model (embeddings, attention weights, feed-forward weights)
In practice, this is implemented as cross-entropy loss between the model's predicted distribution over the vocabulary and the actual next token at each position:
import torch.nn.functional as F
def compute_lm_loss(
model: GPT1Model,
input_ids: torch.Tensor,
) -> torch.Tensor:
"""
Compute the language modeling loss.
The model predicts the next token at each position,
and we compute cross-entropy against the actual next token.
"""
# Get logits from model
outputs = model(input_ids)
logits = outputs["logits"]
# Shift: logits[i] predicts input_ids[i+1]
shift_logits = logits[:, :-1, :].contiguous()
shift_labels = input_ids[:, 1:].contiguous()
# Flatten and compute cross-entropy
loss = F.cross_entropy(
shift_logits.view(-1, shift_logits.size(-1)),
shift_labels.view(-1),
)
return lossBatch size: 4, Sequence length: 64 Language modeling loss: 312.4927 Perplexity: inf
The loss on random input is approximately , which corresponds to perplexity equal to the vocabulary size. This is expected for an untrained model that assigns roughly uniform probability across the vocabulary. Training drives this loss down as the model learns to predict more accurately.

Pre-Training Data
GPT-1 was pre-trained on the BooksCorpus dataset, which contains approximately 7,000 unpublished books totaling about 800 million words. The BooksCorpus was chosen for its long-range coherent text, spanning many pages of continuous narrative. This differs from datasets like Wikipedia, where articles are relatively short and self-contained. In Wikipedia, the maximum coherent narrative length is typically a few paragraphs within a section. In BooksCorpus, the model needed to track characters and plotlines while following themes across thousands of tokens, which is precisely the kind of long-range dependency that makes the learned representations useful for downstream tasks.
The choice to use unpublished books (as opposed to published books) was partly motivated by licensing considerations: unpublished books posted to sites like Smashwords were more freely available. The genre distribution skewed toward romance and fiction, which introduced certain biases into the learned representations. For instance, the model learned more about interpersonal relationships and emotions, including informal dialogue, than it would have from a more balanced corpus. Subsequent models like GPT-2 and GPT-3 used more diverse web-scraped data to address this distribution problem, producing more balanced and general-purpose representations.
The BPE tokenizer trained on the BooksCorpus uses 40,000 merge operations, producing a vocabulary that balances coverage and sequence length. Common words like "the" and "cat" receive single tokens, while rare or morphologically complex words are split into subwords. For instance, "revolutionized" might become "revolution" + "ized", and "transformer" might be a single token if it appears frequently enough in the training data. This subword tokenization allows the model to handle any input text, including words not seen during training, by decomposing them into known subword units. The 40,000 merge vocabulary was chosen as a reasonable tradeoff: larger vocabularies reduce average sequence length but require more embedding parameters and make the output projection harder to learn.
Key characteristics of the pre-training setup:
- Dataset: BooksCorpus (~800M words from ~7,000 books)
- Tokenization: Byte Pair Encoding (BPE) with 40,000 merge operations
- Context window: 512 tokens per training example
- Batch size: 64 sequences
- Training steps: 100 epochs over the dataset
- Optimizer: Adam with learning rate 2.5e-4, linear warmup over 2,000 steps, cosine annealing
The choice of BooksCorpus enabled the model to learn long-range dependencies across paragraphs and chapters. This was critical for the transfer learning hypothesis: if the model learned to predict coherent narratives, it might develop representations useful for understanding meaning, not just local syntax.

Visualizing Pre-Training Dynamics
Let's visualize how next-token prediction works during pre-training. At each position, the model outputs a probability distribution over the vocabulary, and training pushes this distribution toward placing high probability on the actual next token:

The key insight is that this objective provides dense supervision: every position in every training sequence contributes a gradient signal. Unlike masked language modeling (used in BERT), where only 15% of tokens are predicted, causal language modeling uses every token as a training signal. This makes efficient use of the training data.

Fine-Tuning Approach
GPT-1's fine-tuning approach was central to its success. Rather than designing task-specific architectures, the same pre-trained model was adapted to each task with minimal modifications: add a simple classifier head and fine-tune all parameters end-to-end. This simplicity was part of what made the approach so powerful. Previous work on transfer learning in NLP often involved complex procedures: train an ELMo model, freeze its weights, concatenate its outputs with task-specific features, train the task-specific layers. GPT-1 replaced this elaborate pipeline with a clean two-step process: pre-train everything on text, then fine-tune everything on the task.
The key design principle governing fine-tuning is parameter efficiency. Because the pre-trained model already encodes rich linguistic knowledge, the fine-tuning step needs to accomplish very little: it needs to steer the model's existing representations toward task-relevant distinctions, not learn language from scratch. This is why fine-tuning requires only a few epochs and a low learning rate. The model starts from a near-optimal initialization for language understanding tasks, and fine-tuning makes small adjustments to specialize its behavior. A higher learning rate would risk overwriting the pre-trained knowledge, a phenomenon called catastrophic forgetting, where gradient steps driven by task-specific data push the parameters far enough from their pre-trained values that the general language understanding is lost.
The auxiliary language modeling loss during fine-tuning addresses catastrophic forgetting directly. By including the pre-training objective in the fine-tuning loss (with a coefficient ), the model is penalized for drifting too far from its pre-trained behavior. The task-specific labels push the model toward the task, while the language modeling objective acts as an anchor, keeping the representations close to their pre-trained values. This regularization effect is particularly valuable for small fine-tuning datasets, where the task labels alone would quickly overfit the small amount of labeled data.
Input Transformation
The central design choice was to transform each task into a format compatible with the language model's interface. All tasks were converted into sequences of tokens that the model processes left-to-right. This is a non-trivial design challenge: different NLP tasks have very different input structures. Sentiment classification takes a single text. Entailment takes two texts with a logical relationship between them. Similarity takes two texts that should be compared. Multiple-choice question answering takes a context passage and several candidate answers. GPT-1 provides a unified solution: represent all inputs as linear sequences with special delimiter tokens marking the boundaries between text segments.
The special tokens, [Start], [Delim], and [Extract], are added to the vocabulary and their embeddings are learned from scratch during fine-tuning. The [Start] token signals the beginning of a new example. The [Delim] token separates two text segments (e.g., premise from hypothesis in entailment, or context from answer in QA). The [Extract] token (sometimes called the classification token) appears at the end of the sequence, and its final hidden-state representation is used as the input to the classification head. Because of causal attention, the [Extract] token's representation aggregates information from all preceding tokens. This provides a summary of the entire input.

The input transformations follow a consistent pattern:
- Classification:
[Start] text [Extract], where the representation at[Extract]is used for classification - Entailment:
[Start] premise [Delim] hypothesis [Extract], which determines if premise entails hypothesis - Similarity:
[Start] text1 [Delim] text2 [Extract], processing both orderings and averaging - Multiple Choice/QA:
[Start] context [Delim] answer [Extract], scoring each answer independently with softmax over scores
The [Extract] token (sometimes called [CLS] in other models) is a special token whose final representation is used for the classification head. Because of causal attention, this token's representation aggregates information from the entire preceding sequence.
Fine-Tuning Loss
During fine-tuning, GPT-1 uses a combined objective that includes both the task-specific loss and a language modeling auxiliary loss. The combined loss is computed by adding a fraction of the pre-training language modeling objective to the primary task-specific objective:
where:
- : the task-specific loss (e.g., cross-entropy for classification)
- : the ground truth label for the task
- : the input sequence
- : the auxiliary loss weight (set to 0.5 in the original paper)
- : the language modeling loss on the input, computed identically to the pre-training objective
Why does this formula make sense? Notice that depends on but not on : it measures how well the model can predict the tokens in the input sequence, regardless of the task label. This loss is computable for any text sequence, supervised or not. During fine-tuning, the task loss pushes the model toward correct task predictions, while simultaneously pushes the model to maintain its ability to predict tokens in the input. The coefficient means the language modeling objective receives half the weight of the task objective, strong enough to regularize but not so strong as to prevent task learning.
The auxiliary language modeling loss serves two purposes. First, it acts as a regularizer, preventing the model from forgetting useful language patterns during fine-tuning. A model fine-tuned with only task supervision may rapidly overfit the task-specific data, especially for small datasets, while simultaneously degrading at language modeling. The auxiliary loss prevents this degradation. Second, it provides additional gradient signal, particularly useful when task-specific training data is limited. When only a few hundred labeled examples are available, the language modeling objective on the input tokens provides thousands of additional gradient signals per batch, effectively augmenting the training signal.
class GPT1ForClassification(nn.Module):
"""GPT-1 with classification head for fine-tuning."""
def __init__(
self,
base_model: GPT1Model,
num_classes: int,
extract_token_id: int = 40001, # Special [Extract] token
):
super().__init__()
self.base_model = base_model
self.classifier = nn.Linear(768, num_classes)
self.extract_token_id = extract_token_id
def forward(
self,
input_ids: torch.Tensor,
labels: torch.Tensor | None = None,
lm_weight: float = 0.5,
) -> dict[str, torch.Tensor]:
outputs = self.base_model(input_ids)
logits = outputs["logits"]
hidden_states = outputs["last_hidden_state"]
# Find [Extract] token positions (last token in each sequence)
batch_size, seq_len = input_ids.shape
extract_positions = (input_ids == self.extract_token_id).float()
# If no extract token found, use last position
if extract_positions.sum() == 0:
extract_hidden = hidden_states[:, -1, :]
else:
# Get hidden state at extract token position
extract_idx = extract_positions.argmax(dim=1)
extract_hidden = hidden_states[
torch.arange(batch_size), extract_idx
]
# Classification logits
class_logits = self.classifier(extract_hidden)
result = {"class_logits": class_logits, "lm_logits": logits}
if labels is not None:
# Task loss (classification)
task_loss = F.cross_entropy(class_logits, labels)
# LM loss (auxiliary)
shift_logits = logits[:, :-1, :].contiguous()
shift_labels = input_ids[:, 1:].contiguous()
lm_loss = F.cross_entropy(
shift_logits.view(-1, shift_logits.size(-1)),
shift_labels.view(-1),
)
# Combined loss
total_loss = task_loss + lm_weight * lm_loss
result["loss"] = total_loss
result["task_loss"] = task_loss
result["lm_loss"] = lm_loss
return resultClassification logits shape: torch.Size([4, 3]) Total loss: 146.2779 Task loss: 1.4628 LM auxiliary loss: 289.6301
The classification head adds minimal parameters (just 768 × num_classes), keeping fine-tuning efficient. The combined loss balances learning the task while maintaining the language model's learned representations.
Fine-Tuning Hyperparameters
GPT-1 used the following hyperparameters for fine-tuning:
- Learning rate: 6.25e-5 (lower than pre-training)
- Batch size: 32
- Epochs: 3 (most tasks)
- LM auxiliary weight (): 0.5
- Warmup: Linear warmup over 0.2% of training
- Dropout: 0.1 on classifier, 0.1 in attention/residual
The lower learning rate prevents catastrophic forgetting of pre-trained knowledge. Just 3 epochs were typically sufficient because the model started from a strong initialization. This contrasts sharply with training from scratch, which might require hundreds of epochs.

Transfer Learning Results
GPT-1 demonstrated strong transfer learning across 12 diverse NLP tasks. The pre-training on BooksCorpus, despite never seeing task-specific supervision, produced representations that transferred effectively to classification and similarity tasks, as well as question answering. This result validated the central hypothesis of the paper: that a model trained purely to predict text can develop general-purpose language representations without any explicit semantic annotation.
The breadth of the transfer was striking. The same pre-trained model, fine-tuned separately, improved over the state of the art on sentiment classification (a relatively straightforward task), natural language inference (which requires logical reasoning), semantic textual similarity (which requires understanding paraphrase and meaning equivalence), commonsense reasoning (COPA), and multi-paragraph reading comprehension (RACE). These tasks were sufficiently different that it would not have been obvious, prior to GPT-1, that a single set of pre-trained representations could serve all of them well. The diversity of the gains was arguably more significant than the magnitude, because it suggested that the pre-trained representations captured something fundamental about language rather than patterns specific to any one task type.
The pattern of improvements also revealed something about what pre-training provides. The largest gains appeared on tasks with limited training data (RACE with 87,866 examples, COPA with 400 training examples) and on tasks requiring reasoning over longer contexts (reading comprehension). Tasks where large training sets already existed showed smaller improvements, consistent with the view that pre-training is most valuable when labeled data is scarce. When you have millions of labeled examples, supervised learning alone can learn the relevant patterns. When you have only hundreds or thousands, the pre-trained representations provide a strong initialization that compensates for data scarcity.
Benchmark Performance
The following table summarizes GPT-1's performance compared to previous state-of-the-art models at the time of publication (June 2018):
| Task | Dataset | GPT-1 | Previous SOTA | Improvement |
|---|---|---|---|---|
| Classification | SST-2 | 91.3 | 90.2 | +1.1 |
| Classification | CoLA | 45.4 | 35.0 | +10.4 |
| Similarity | STS-B | 82.0 | 81.0 | +1.0 |
| Similarity | QQP | 70.3 | 66.1 | +4.2 |
| Entailment | MNLI | 82.1 | 80.6 | +1.5 |
| Entailment | QNLI | 88.1 | 82.3 | +5.8 |
| Reading Comp. | RACE | 59.0 | 44.1 | +14.9 |
| Commonsense | COPA | 78.6 | 71.2 | +7.4 |
The improvements were particularly dramatic on tasks with limited training data. RACE, a reading comprehension dataset, saw a 14.9 point improvement. CoLA, a grammatical acceptability task, improved by 10.4 points. These gains suggest that pre-training captures linguistic knowledge that is difficult to learn from small supervised datasets alone.
Understanding Transfer Dynamics
Let's examine how the pre-trained model transfers knowledge. The key question is: what does the model learn during pre-training that helps with downstream tasks? The answer is not a single thing but a hierarchy of linguistic capabilities that emerge at different layers of the network. Research on probing classifiers, which train simple linear models on the representations from each layer to predict linguistic properties, has revealed a consistent pattern: lower layers capture local syntactic features like part-of-speech tags and constituent boundaries, while higher layers capture more abstract semantic and discourse properties. This hierarchical organization parallels what has been observed in convolutional neural networks for images, where earlier layers detect edges and textures while later layers detect object parts and semantic categories.
The GPT-1 paper's own ablation studies examined what happens when you fine-tune only the top layers and keep the bottom layers frozen. Performance improves monotonically with : using all 12 layers beats using 11, which beats using 10, and so on. This means every layer contributes useful pre-trained knowledge to downstream performance, and there is no clear cutoff where the lower layers stop contributing. The implication is that the full depth of the pre-trained representation is relevant for transfer; top-level semantic features alone are insufficient.
The diminishing-returns pattern in the ablation also makes intuitive sense. The first few layers of pre-training produce enormous gains because they capture basic syntactic and semantic regularities that are useful for almost any NLP task. The later layers contribute more specialized discourse and reasoning capabilities that are valuable but less universally necessary. This pattern suggests that if compute is limited, the most cost-effective strategy is to invest in pre-training depth up to a point, then accept diminishing returns on additional layers.

The figure shows simulated data based on patterns from the GPT-1 paper's ablation studies. Key observations:
- All layers contribute: Each additional pre-trained layer improves performance
- Diminishing returns: The marginal benefit decreases as more layers are added
- Task variation: Some tasks (like SST-2) benefit more from deeper features than others
Ablation Studies
The GPT-1 paper included several ablation studies that revealed what mattered for transfer learning. Ablation studies systematically remove or disable components of the model to measure each component's individual contribution. By comparing the full model against versions with specific components removed, researchers can distinguish which design choices contribute to performance from those that are present without affecting it. The GPT-1 ablations addressed three key questions: Does pre-training help? Does the auxiliary LM loss help? Does the transformer architecture help (compared to a simpler LSTM baseline)?

The ablations reveal:
- Pre-training drives the gains: Without pre-training, performance drops 5-15 points across tasks
- Auxiliary LM loss helps: The language modeling objective during fine-tuning provides consistent improvement, especially on smaller datasets
- Transformer architecture matters: Comparisons with LSTM-based models showed the transformer's self-attention mechanism was important for capturing long-range dependencies

GPT-2 Model Configuration (similar to GPT-1): Vocabulary size: 50,257 Hidden size: 768 Number of layers: 12 Number of heads: 12 Context window: 1024 Total parameters: 124,439,808
Generating Text
The pre-trained model can generate coherent text continuations:
def generate_text(prompt, max_new_tokens=20):
"""Generate text continuation using the pre-trained model (greedy decoding)."""
inputs = tokenizer(prompt, return_tensors="pt")
with torch.no_grad():
outputs = gpt2_model.generate(
inputs["input_ids"],
max_new_tokens=max_new_tokens,
do_sample=False,
pad_token_id=tokenizer.eos_token_id,
)
generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
return generated_textThe model generates coherent continuations because it learned to predict likely next tokens during pre-training. The quality of these completions reflects the knowledge captured from the training corpus.
Extracting Representations for Transfer
For transfer learning, we extract the hidden states at specific positions to use as input features for downstream classifiers:
def extract_representations(texts, layer=-1):
"""
Extract representations from a specific layer.
Args:
texts: List of input texts
layer: Which layer to extract from (-1 = last layer)
Returns:
Tensor of representations, shape (num_texts, hidden_size)
"""
inputs = tokenizer(
texts,
return_tensors="pt",
padding=True,
truncation=True,
max_length=512,
)
with torch.no_grad():
outputs = gpt2_model(
input_ids=inputs["input_ids"],
attention_mask=inputs["attention_mask"],
output_hidden_states=True,
)
# Get hidden states from specified layer
hidden_states = outputs.hidden_states[layer]
# Use last non-padding token's representation
seq_lengths = inputs["attention_mask"].sum(dim=1) - 1
batch_size = hidden_states.size(0)
representations = hidden_states[torch.arange(batch_size), seq_lengths]
return representationsExtracted representations shape: torch.Size([3, 768]) Representation dimension: 768 Cosine similarities between representations: Text 1 vs Text 2: 0.9777 Text 1 vs Text 3: 0.9967 Text 2 vs Text 3: 0.9669
These final-token representations contain contextual information, but their raw cosine similarities can remain uniformly high. GPT-2 was trained for next-token prediction, not to produce a calibrated sentence-embedding space. The comparison below makes that limitation visible: small relative differences exist, but a dedicated pooling strategy or sentence-level fine-tuning is needed before treating these vectors as semantic similarity scores.

Layer-wise Representations
Different layers capture different levels of abstraction. Let's visualize how representations evolve through the network:

The similarity matrix reveals the structure of information flow through the network. Early layers remain close to the embedding space, while deeper layers transform representations more dramatically. For transfer learning, intermediate layers often provide the best features because they capture generalizable linguistic patterns without becoming too specialized to the pre-training objective.
Limitations and Impact
GPT-1 established the "pre-train then fine-tune" paradigm, but it came with significant limitations that subsequent work addressed. These limitations matter as historical record and as the motivation for research directions that followed, including BERT, GPT-2, GPT-3, and the instruction-tuned models that dominate current NLP.
The 512-token context window restricted the model to relatively short documents. Question answering over long passages or multi-document reasoning required chunking text, potentially losing context across chunks. Consider a task like answering questions about a 2,000-word article: GPT-1 must process the article in overlapping windows and somehow combine the evidence across chunks, a brittle and information-lossy process. Subsequent models like GPT-2 (1024 tokens), GPT-3 (2048 tokens), and modern long-context models (100K+ tokens) progressively addressed this limitation. The underlying technical challenge is that self-attention scales quadratically with sequence length in both compute and memory, so extending context requires either hardware improvements, architectural modifications (like sparse attention), or both.
The fine-tuning approach, while effective, required separate training runs and separate model instances for each downstream task. If you needed to deploy GPT-1 for both sentiment analysis and question answering, you needed two fine-tuned models, each taking significant compute and storage. At the scale of GPT-1 (117M parameters), this was manageable, but at the scale of GPT-3 (175B parameters), maintaining dozens of task-specific fine-tuned copies becomes impractical. This motivated research into few-shot and zero-shot learning, where a single frozen model handles diverse tasks through prompting alone, and parameter-efficient fine-tuning methods like LoRA and adapters that modify only a small fraction of the parameters.
The pre-training data introduced biases that are difficult to fully characterize. BooksCorpus skews heavily toward romance and fiction written in English, published between roughly 2010 and 2016. The model reflects cultural assumptions and stereotypes, along with the linguistic patterns embedded in that genre. It may perform differently on text from different domains, time periods, languages, or cultural contexts, and it may encode and amplify social biases present in the fiction corpus. This prompted serious research into data curation, bias evaluation, and debiasing techniques that continues to this day. The lesson was that the training data distribution shapes the model's behavior in deep ways, and choosing the right data is as important as choosing the right architecture.
Despite these limitations, GPT-1 changed subsequent NLP research. It showed definitively that unsupervised pre-training on raw text produces representations that transfer effectively to diverse supervised tasks, validating a hypothesis that had been tentatively explored by earlier work on word embeddings and ELMo but never demonstrated at the level of complete sentence understanding. This result led researchers toward a new approach: invest compute in large-scale pre-training and adapt through fine-tuning, rather than designing task-specific architectures for each application. The simplicity and effectiveness of this recipe made it immediately reproducible by the broader research community, accelerating progress across the entire field.
GPT-1 also established the decoder-only transformer as a viable architecture for language understanding, not just generation. While BERT (released four months later) temporarily shifted attention to encoder-only models for understanding tasks because bidirectional attention seemed advantageous for classification, the trajectory from GPT-1 through GPT-2 and GPT-3 showed that sufficiently large decoder models could match or exceed encoder performance on understanding tasks while retaining generation capabilities. This insight, that you don't need to choose between a model that understands and a model that generates, because a sufficiently powerful decoder does both, proved to be one of the most consequential results in recent NLP history. We explore the scaling behavior that made this possible in the next chapter on GPT-2.

The fine-tuning approach, while effective, required task-specific training data and produced separate models for each task. A single GPT-1 model could not simultaneously perform classification and translation, as well as question answering. This motivated research into zero-shot and few-shot learning, culminating in GPT-3's in-context learning capabilities where a single model handles diverse tasks through careful prompting alone.
The model's 117M parameters, substantial for 2018, proved small relative to what was possible. The scaling hypothesis, later formalized in neural scaling laws, showed that larger models trained on more data consistently improved performance. GPT-2 (1.5B parameters) and GPT-3 (175B parameters) validated this direction, though also raised concerns about compute accessibility and environmental impact.
The pre-training data (BooksCorpus) introduced biases present in published fiction. The model reflected patterns and stereotypes, as well as perspectives found in those texts. This prompted research into data curation, debiasing techniques, and more careful evaluation of model behavior across different demographic groups.
Despite these limitations, GPT-1 had significant impact. It showed that unsupervised pre-training on raw text produces representations that transfer effectively to diverse supervised tasks. This finding shifted NLP toward a new approach: instead of designing task-specific architectures, invest compute in large-scale pre-training and adapt through fine-tuning. The simplicity of this recipe, combined with its effectiveness, made it the dominant paradigm.
GPT-1 also established the decoder-only transformer as a viable architecture for language understanding, not just generation. While BERT (released four months later) temporarily shifted attention to encoder-only models for understanding tasks, the trajectory from GPT-1 through GPT-2 and GPT-3 demonstrated that sufficiently large decoder models could match or exceed encoder performance on understanding tasks while also enabling generation.
Key Parameters
When working with GPT-1-era models for transfer learning, these parameters have the greatest impact on performance. Understanding why each parameter matters requires thinking about the two-phase nature of the approach: the pre-trained model is a carefully optimized starting point, and fine-tuning is a controlled perturbation of that starting point toward a task-specific objective. The goal is to move far enough to specialize for the task but not so far as to destroy the general-purpose representations.
-
Learning rate: Fine-tuning typically uses 1-2 orders of magnitude lower learning rate than pre-training (e.g., 2-6e-5 vs 2.5e-4). Higher rates risk catastrophic forgetting of pre-trained knowledge. The intuition is that the pre-trained model already resides in a good region of parameter space; large gradient steps would carry it far from that region before the task-specific signal can guide it back to a good local optimum.
-
Epochs: 2-4 epochs usually suffice for fine-tuning. Unlike training from scratch, the model starts from a strong initialization and quickly adapts to the task. Training for more epochs tends to overfit the fine-tuning data, especially for small datasets, as the model begins to memorize training examples rather than generalize.
-
Batch size: 16-32 is typical for fine-tuning. Larger batches can speed training but may require learning rate adjustment. For very small fine-tuning datasets (under 1,000 examples), smaller batches with more gradient steps may help by providing more frequent parameter updates.
-
Auxiliary LM weight (): 0.5 as recommended in the paper, but can be tuned per task. Higher values provide more regularization, useful for smaller datasets. On very large fine-tuning datasets (100K+ examples), you can often reduce or set it to zero, since the abundant labeled data reduces the risk of overfitting.
-
Dropout: 0.1 in attention and feed-forward layers. Can be increased for very small fine-tuning datasets to prevent overfitting. The interaction between dropout and auxiliary LM loss means that both regularization mechanisms together can be more effective than either alone.
-
Layer selection: For feature extraction (frozen model), intermediate layers (6-9 for a 12-layer model) often outperform the final layer, which becomes specialized for next-token prediction. The final layer's representations are optimized for language modeling, which may not align with the feature requirements of your downstream task. Intermediate layers retain more general-purpose linguistic structure.
-
Warmup: Linear warmup over 0.2% of training steps helps stabilize early training when fine-tuning. Warmup prevents large early gradient steps (which can destabilize the pre-trained representations) by gradually increasing the learning rate from a near-zero value to the target rate over the first few hundred steps.
Summary
GPT-1 introduced a powerful recipe for language understanding: pre-train a transformer decoder on large-scale text using next-token prediction, then fine-tune on downstream tasks with minimal architectural changes. The key contributions and takeaways include:
-
Unified architecture: A single 12-layer transformer decoder handles both pre-training and diverse downstream tasks. The same model structure enables text generation and classification.
-
Generative pre-training: The simple objective of predicting the next token, applied at scale to BooksCorpus, produces representations rich enough for transfer learning across classification and entailment, along with similarity and question answering.
-
Input transformation: Different tasks are reformulated as sequences with special delimiters (
[Start],[Delim],[Extract]), allowing the same model to process various input formats. -
Auxiliary objectives: Including language modeling loss during fine-tuning () improves transfer by regularizing against forgetting.
-
Transfer across tasks: Pre-training on narrative text transferred to formal reasoning tasks (RACE, COPA). This shows that language modeling captures general linguistic competence.
GPT-1 set the stage for the scaling revolution that followed. GPT-2 scaled the approach 10x, GPT-3 scaled it 1000x, and subsequent models have pushed further still. But the core insights, decoder-only architecture, pre-training on raw text, fine-tuning for tasks, remain foundational to how we build language AI today.
GPT-1 Architecture and Pre-Training
Reference
Citation details
Cite or share this article.
Continue with the full handbook
This chapter is part of Language AI Handbook. Use the handbook page to browse the complete table of contents and continue reading in sequence.
Explore Language AI HandbookStay up to date
Get articles, book updates, and news delivered to your inbox.
No spam, unsubscribe anytime.
Join the community
Sign in to remove popups, track your reading progress, and join the discussion.

Comments
No comments yet. Be the first to share your thoughts!