YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

Assignment 1 Report — Transformers from Scratch, Ablations, and BLT


1. Introduction and Task

  • Task: sequence-to-sequence deciphering. Source = binary cipher strings (8 bits per plaintext character); target = plaintext English (brown_cipher.txt / brown_plain.txt, 5,000 line-aligned pairs).
  • Goal: implement a full encoder–decoder transformer from basic PyTorch ops (no nn.Transformer / nn.MultiheadAttention) and run a controlled five-way ablation over positional encoding, attention, normalization, and tokenization (Table 1 in the assignment).
  • Cipher (own analysis): repeating-key XOR with key ANLP2026, i.e. cipher_byte[i] = ord(plain[i]) XOR key[i % 8]. Equivalent to eight conflict-free substitution tables indexed by position mod 8. The mapping is exactly solvable given absolute position (or a recoverable start anchor), and source byte i aligns 1:1 with plaintext character i.

2. Implementation Overview

2.1 Core modules (all from scratch)

  • Scaled dot-product attention: softmax(QKᵀ/√d_k)V with additive −inf masking (src/models/attention.py). Mask convention: 1/True = attend.
  • MHA: 8 heads, learned Q/K/V/O projections, heads split/merged by reshape.
  • GQA: 8 query heads share 2 KV heads; K/V projected to n_kv·d_head and expanded with repeat_interleave. Cuts KV projection parameters 4×.
  • Positional encodings:
    • C1/C3/C4/C5: sinusoidal absolute PE added to token embeddings.
    • C2: RoPE applied to Q and K in self-attention and cross-attention (target queries and source keys rotated by their own positions). Source sequences also begin with BOS so relative rotations have a clear line start. Sinusoidal PE is not added when RoPE is active.
  • Normalization: LayerNorm and RMSNorm from elementary ops; Pre-LN everywhere (x = x + sublayer(norm(x))).
  • FFN: position-wise 256→1024→256 with GELU.
  • Seq2Seq transformer: 4 encoder + 4 decoder layers, d_model 256, embeddings scaled by √d_model, padding + causal masks, untied output head.

2.2 BLT modules (C5)

  • LocalEncoder (bytes → patches): byte embedding (d_local 128) + sinusoidal PE + 2 light transformer layers, then masked mean-pooling over fixed 4-byte patches, projected to d_model 256.
  • Global transformer: same 4+4 stack as C1, but on patch sequences (length ÷4).
  • LocalDecoder (patches → bytes): global decoder outputs are shifted right by one patch (learned start-patch), upsampled 4×, combined with byte embeddings, passed through 2 light causal layers, then a byte head.
  • Causality: (1) patch-level causal mask in the global decoder, and (2) byte-level causal mask in the target-side local encoder. Without (2), bidirectional local attention leaks future bytes into patch vectors before the global causal mask can help (Section 5.4).

2.3 Tokenization

  • Subword (C1–C4): from-scratch BPE (whitespace pre-tokenization, </w> end-of-word marker), vocab 64 (7 merges; ~1.16 characters per token). Compact vocab keeps targets near character-aligned with the cipher while remaining “standard subword.” Trained on the train split only. Source: each 8-bit group → id 0–255 (+ specials), with BOS and EOS.
  • Token-free (C5): raw UTF-8 bytes on both sides, vocab 260.

2.4 Training setup

Shared across all five configs: batch 8, AdamW (lr 3e-4, weight decay 0.01), 1,000-step warmup + cosine decay, grad clip 1.0, dropout 0.1, 30 epochs, CE ignoring PAD, seed 42. Split 4,000 / 500 / 500. Joint truncation to 510 characters (room for BOS+EOS). Hardware: RTX 3060 Laptop (6 GB). WandB logging; best-val checkpoints for HuggingFace upload.

3. Evaluation Protocol

All numbers use greedy decoding on the 500-example test set.

  • Bit-level accuracy: decode to text, re-encode pred/ref as 8 bits/char, compare position-wise over the longer length. Tokenizer-independent → primary metric across C1–C5.
  • Sequence accuracy: exact string match.
  • Levenshtein distance: mean character edit distance.
  • BLEU / ROUGE-1/2/L: tokenized models only (C1–C4). BLEU = sacreBLEU score on the 0–100 scale.
  • Efficiency: tokens/sec and peak GPU memory in training, s/epoch, and wall-clock greedy decode time.

4. Results

4.1 Main table (test set, greedy decoding)

Config Bit Acc ↑ Seq Acc ↑ Levenshtein ↓ BLEU ↑ ROUGE-1 ↑ ROUGE-L ↑ Val loss ↓ Params
C1 base 0.800 0.028 18.1 70.2 0.861 0.860 0.172 7.47M
C2 RoPE 0.989 0.850 0.28 99.4 0.993 0.993 0.0016 7.47M
C3 GQA 0.763 0.0 45.9 46.7 0.733 0.730 0.260 6.29M
C4 RMSNorm 0.805 0.038 11.8 77.9 0.898 0.898 0.109 7.47M
C5 BLT 0.971 0.002 24.2 n/a n/a n/a 0.106* 8.80M

*C5 loss is per-byte, not per-subword — not directly comparable to C1–C4.

4.2 Efficiency table

Config s/epoch ↓ Train tokens/s ↑ Peak GPU mem (MB) ↓ Greedy decode, 500 ex. (s) ↓
C1 base 85.4 16,589 2,615 451
C2 RoPE 88.8 15,963 2,611 487
C3 GQA 80.7 17,550 2,601 416
C4 RMSNorm 83.2 17,026 2,538 449
C5 BLT 39.0 42,035 (bytes) 1,207 293

(C5 tokens/s counts bytes; s/epoch is the fair speed comparison.)

Plots: bar_bit_accuracy.png, bar_mean_levenshtein.png, bar_bleu.png, c1_vs_c5_memory.png, c1_vs_c5_speed.png, c1_vs_c5_epoch_time.png, plus train/val curves from *_history.json / WandB.

5. Analysis and Discussion

5.1 Representation matters as much as the transformer stack

An earlier BPE vocab of 4,000 left C1–C4 at BLEU <1 and val CE 4.8 even though the architecture could overfit a single batch to BLEU 100. Large-vocab BPE (3.8 chars/token) destroyed the cipher’s 1:1 positional alignment and forced the decoder to recover soft alignments while classifying among 4,000 tokens. Switching to a compact 64-token BPE (~1.16 chars/token), adding source BOS, and enabling RoPE on cross-attention raised C1 to BLEU 70.2 with on-topic decipherment (see outputs/c1_base_samples.json). Include a train/val loss curve here.

5.2 Single-component ablations vs C1

  • C2 (RoPE): best overall (BLEU 99.4, sequence accuracy 85%, val loss 0.0016). With BOS and cross-attention RoPE, relative source–target offsets make this monotonic cipher nearly trivial; sample predictions are near-exact.
  • C3 (GQA): fewer parameters (6.29M vs 7.47M) and fastest subword epochs (80.7s), at a clear quality cost (BLEU 46.7 vs 70.2). Expected capacity/speed tradeoff for 2 shared KV heads on a small model.
  • C4 (RMSNorm): better than base (BLEU 77.9 vs 70.2, val 0.109 vs 0.172, slightly less memory). Dropping mean-centering / bias helps here.
  • C5 (BLT): strongest bit accuracy among non-RoPE models (0.971) and lowest peak memory (1,207MB). Predictions are readable with scattered character errors; BLEU/ROUGE are n/a without a tokenizer.

5.3 BLT tradeoffs (C5 vs C1) — required focus

  • Quality: bit accuracy 0.971 vs 0.800. Levenshtein 24.2 vs 18.1 — compact-BPE C1 is slightly cleaner on edit distance; C5 wins on bits.
  • Memory: 1,207MB vs 2,615MB (−54%). Global layers run on patch sequences (length ÷4).
  • Training speed: 39.0 vs 85.4 s/epoch (−54%).
  • Inference: C5 greedy decode is faster than long compact-BPE decode here (293s vs 451s for 500 examples); patching amortizes work even though generation is per-byte.
  • Metrics: report BLEU/ROUGE only for C1–C4, as the assignment specifies.

5.4 Causality bug found and fixed in BLT (strong viva material)

An early C5 run had suspiciously low teacher-forced loss but degenerate greedy output (“deeee…”). The target-side local encoder used bidirectional byte self-attention before patch pooling, so patch vectors already contained future bytes; the patch-level causal mask downstream could not undo that leakage. Fix: byte-level causal masking in the target-side local encoder (source side stays bidirectional). Perturbation check: changing byte 100 leaves logits at positions <100 unchanged. After the fix (and the shared training fixes above), final C5 reaches val loss 0.106 and bit accuracy 0.971. Lesson: in hierarchical decoders, causality must hold at every level, not only the top.

5.5 Limitations / future work (short)

  • Joint truncation to 510 characters discards the long tail of lines (median length ~554); full-line BLEU against untruncated references would be capped even with perfect known-prefix predictions.
  • Greedy decoding only (per assignment); beam search would likely improve C1/C3/C5 further.
  • BLT uses fixed 4-byte patches; entropy-based dynamic patching (original BLT paper) is the natural next step.
  • Compact BPE (64) is still “standard subword” but near character-level; report this design choice explicitly.

6. Reproducibility

  • bash scripts/run_all.sh trains and evaluates all five configs sequentially with thermal cooldowns (configs/*.yaml, seed 42).
  • WandB run links: [TODO]. HuggingFace checkpoint repo: [TODO].
  • Per-config metrics: outputs/<config>_metrics.json; samples: outputs/<config>_samples.json; aggregate: outputs/results_table.md.

References (excluded from page count)

  • Vaswani et al., Attention Is All You Need, 2017.
  • Su et al., RoFormer: Enhanced Transformer with Rotary Position Embedding, 2021.
  • Ainslie et al., GQA: Training Generalized Multi-Query Transformer Models, 2023.
  • Zhang & Sennrich, Root Mean Square Layer Normalization, 2019.
  • Pagnoni et al., Byte Latent Transformer: Patches Scale Better Than Tokens, 2024.
  • Sennrich et al., Neural Machine Translation of Rare Words with Subword Units, 2016.
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support