Deep Learning/Generative Pre-trained Transformer
36 / 67

09/2023Deep Learning

Generative Pre-trained Transformer

A GPT built from scratch in PyTorch — causal self-attention, learned positional embeddings, and six pre-norm transformer blocks — trained character by character on a corpus of 2023 AI articles and served behind a FastAPI endpoint.

╌╌╌╌

A character-level GPT implemented from scratch in PyTorch — every module written out by hand, no nn.Transformer shortcuts. It trains on a corpus of 2023 AI and technology writing (the siavava/ai-tech-articles dataset, filtered to that year), building its vocabulary from the sorted set of characters in the text, and generates one character at a time.

Attention works as a soft lookup: each token emits a query, a key, and a value, and attends to the others by how well its query matches their keys:

with the keeping dot products in softmax's well-behaved range. In code a Head is three bias-free nn.Linear projections into a head_size subspace, a registered lower-triangular tril buffer for the causal mask that zeroes attention to future positions, and dropout on the weights. MultiHeadAttention runs six such heads in parallel () and projects their concatenation back to the model width, so different heads track different relationships.

Both sublayers of a pre-norm transformer block sit on a residual stream — each adds its contribution to a running sum, which is what lets dozens of blocks train stably.

A Block is pre-norm: x = x + sa(ln1(x)) then x = x + ffwd(ln2(x)), where FeedFoward widens to four times the model dimension through a ReLU and back. GPTLanguageModel stacks six of these in an nn.Sequential, fronted by a token embedding table and a learned position embedding table — attention alone is permutation-invariant, so the positions supply order — and closed by a final LayerNorm and an lm_head linear tie to the vocabulary. Weights initialize from a normal with standard deviation 0.02.

The trained configuration (config.yml) is small enough to run on one GPU:

  • context 256 tokens, model width 384, heads 6, layers 6.
  • dropout 0.2, batch 32, AdamW at learning rate .
  • 10,000 iterations, with train and validation loss estimated over 200 batches every 500 steps.

Training minimizes cross-entropy

and generate samples autoregressively — crop the context to the last 256 tokens, softmax the final logits, draw one character with torch.multinomial, append it, and repeat. A FastAPI layer (main.py) loads a saved checkpoint and exposes GET /api/{query}, returning 150 generated characters as JSON.

References

  1. Project repository
  2. Reference notes: Deep Learning
  3. Reference notes: Linear Algebra

╌╌ END ╌╌