Summary by TwinMind ยท 4h 1m 26s

Let's reproduce GPT-2 (124M)

Andrej Karpathy

Let's reproduce GPT-2 (124M) Andrej Karpathy

Andrej Karpathy1.38M subscribers

Introduction to GPT-2 Reproduction

  • Goal: Reproduce GPT-2 (124 million parameter version)
  • OpenAI released GPT-2 in 2019 with blog post, paper, and GitHub code
  • GPT-2 consists of models at different sizes (miniseries)
    • Smallest: 124M parameters (12 layers, 768 dimensions)
    • Largest: 1.5B parameters
  • Different model sizes help establish scaling laws
    • Plotting model size vs downstream metrics shows performance trends
  • Paper had error in parameter counts (corrected in GitHub repo)
  • Modern reproduction takes ~1 hour, costs ~$10 on cloud compute

GPT-2 Architecture and Loading Weights

  • OpenAI released model weights, unlike many other models
  • GPT-2 paper lacks training details; will reference GPT-3 paper for some parameters
  • Loading pre-trained GPT-2 model using Hugging Face Transformers
    • Model architecture includes transformer blocks, embeddings, and output head
  • Testing pre-trained model with text generation
    • Example prompt: "Hello I'm a language model"
  • Creating custom PyTorch implementation of GPT-2 for better understanding
    • Implementing transformer blocks, attention mechanism, and MLP components
    • Using GELU activation function (specifically the approximate version with tanh)
  • Successfully loading OpenAI's weights into custom implementation
    • Verifying with text generation using same prompt

Model Architecture Details

  • GPT-2 is a decoder-only transformer
    • No encoder or cross-attention components
    • Uses pre-normalization (layer norms before attention/MLP blocks)
    • Additional layer normalization after final self-attention block
  • Block structure:
    • Self-attention mechanism with multiple heads
    • MLP with GELU activation
    • Residual connections around each component
  • Attention is communication operation (tokens exchange information)
  • MLP operates independently on each token (no information exchange)
  • Transformer = repeated application of map-reduce pattern
    • Attention = reduce operation
    • MLP = map operation

Training the Model from Scratch

  • Setting up training data (initially using tiny Shakespeare dataset)
  • Creating data loader for batching sequences
    • Handling token sequences and targets for next-token prediction
  • Implementing loss function using cross-entropy
  • Setting up optimizer (AdamW)
  • Initial training with random initialization
    • Expected loss at initialization: ~10.82 (1/vocab_size)
    • Training loop with gradient calculation and parameter updates
  • Weight tying between token embeddings and output projection
    • Reduces parameter count by ~30% (40M parameters)
    • Same weights used at input embedding and output classification
    • Supported by research showing benefits for similar tokens

Initialization and Training Details

  • Implementing initialization following GPT-2 code:
    • Linear layers: normal distribution with std=0.02
    • Biases: zeros
    • Layer norms: weight=1.0, bias=0.0
  • Special initialization scaling for residual paths
    • Scale weights by 1/sqrt(number of residual layers)
    • Prevents variance explosion in residual stream
  • Setting up learning rate scheduler
    • Cosine decay with warmup following GPT-3 paper
    • Warmup over first 375M tokens, decay to 10% of max value
  • Gradient clipping at global norm of 1.0
  • Weight decay of 0.1 (not applied to biases and 1D tensors)

Performance Optimizations

  • Using tensor cores with reduced precision
    • TF32: 8x theoretical speedup with minimal accuracy impact
    • Achieved ~3x speedup (memory bandwidth limited)
  • Mixed precision training with BFloat16
    • Maintains full dynamic range unlike FP16
    • No need for gradient scaling
    • Further improved performance
  • Implementing torch.compile
    • Reduced Python overhead and GPU read/writes
    • 2.3x improvement with single line of code
    • Kernel fusion optimization explained
  • Using Flash Attention
    • 27% improvement over standard attention
    • Avoids materializing full attention matrix
    • Uses online softmax calculation
  • Optimizing vocabulary size for GPU efficiency
    • Changed from 50,257 to 50,304 tokens (power-of-two friendly)
    • 4% speedup despite doing more computation
    • Helps with GPU kernel efficiency

Scaling to Multiple GPUs

  • Implementing Distributed Data Parallel (DDP)
  • Setting up process groups with torch.distributed
  • Modifying data loader to handle multiple processes
    • Each GPU processes different parts of dataset
  • Implementing gradient accumulation
    • Simulating larger batch sizes than what fits in GPU memory
    • Careful handling of loss normalization
  • Synchronizing gradients across GPUs
  • Handling validation and metrics across processes

Training on High-Quality Data

  • Switching from Shakespeare to Fine-Web-EDU dataset
    • 10B token sample of high-quality educational content
    • Pre-processed and tokenized into shards
  • Setting up training for full run
    • Batch size matching GPT-3 paper (0.5M tokens)
    • Processing ~1.5M tokens/second with 8 GPUs
    • Full training run: ~1.7 hours for 10B tokens

Evaluation and Results

  • Implementing validation loss tracking
  • Adding HellaSwag evaluation
    • Multiple-choice benchmark for natural language understanding
    • Using native token completion approach
  • Implementing text sampling to check generation quality
  • Results after training:
    • Surpassed GPT-2 124M validation loss
    • Achieved 33.2% on HellaSwag (surpassing original GPT-2's 29.5%)
    • Approaching GPT-3 124M performance with only 40B tokens (vs 300B)
    • Generated coherent text completions

Advanced Implementation and Future Work

  • Added checkpointing functionality
  • Reference to LLM.c - a pure CUDA implementation
    • Faster than PyTorch version
    • Same numerical results
  • Noted limitations and improvements:
    • Data shuffling improvements needed
    • Torch.compile compatibility issues with evaluation
    • Potential for higher learning rates