Cipher-to-plaintext Transformers (Advanced NLP, Assignment 1)

Encoder-decoder Transformers built from scratch (no nn.Transformer or nn.MultiheadAttention) that decrypt a position-periodic substitution cipher back to English. Five configurations differing from the C1 base by exactly one component each.

Tokenization is hand-written too: a from-scratch BPE over the raw bit string on the cipher side and over characters on the English side (C1-C4), and byte-level input with entropy-chosen patches for C5. data/bpe_*.json and data/entropy_ngram.npz are part of the checkpoint -- the weights are unusable without them.

Measured on the whole 1000-line test split (data/splits/test.txt) under greedy decoding: each line is tiled into windows, decoded, reassembled, and scored as a whole line. C5's BLEU and ROUGE-L read --, not 0 -- the assignment restricts them to tokenized models and C5 is byte-level.

Config Seq. acc. Lev. (mean) Lev. (median) BLEU ROUGE-L Bit acc.
C1 base 0.0160 0.0681 0.0607 0.7205 0.8511 0.7465
C2 RoPE 0.1040 0.0166 0.0129 0.8997 0.9504 0.8363
C3 GQA 0.0080 0.0982 0.0874 0.6438 0.8048 0.7356
C4 RMSNorm 0.0190 0.0745 0.0651 0.7081 0.8425 0.7441
C5 BLT 0.0020 0.1942 0.1844 -- -- 0.9269

Cost

Config Params s/epoch Peak GPU mem (GB)
C1 base 8,948,736 25.7 2.34
C2 RoPE 8,948,736 26.6 2.33
C3 GQA 7,764,480 26.1 2.32
C4 RMSNorm 8,943,104 25.3 2.16
C5 BLT 12,905,987 30.4 1.62

Files

c1/best.ckpt .. c5/best.ckpt   one checkpoint per configuration
data/bpe_plain.json            plaintext BPE vocabulary (C1-C4)
data/bpe_cipher.json           cipher BPE vocabulary (C1-C4)
data/entropy_ngram.npz         order-1 entropy estimator for C5's patcher
data/splits/                   the train/test partition behind every number
hf download aadith-warrier/anlp-a1-cipher-transformer --local-dir anlp-a1

Loading a checkpoint

import torch
from omegaconf import OmegaConf
from models.transformer import build_model

ck = torch.load('c1/best.ckpt', map_location='cpu', weights_only=False)
cfg = OmegaConf.create(ck['hyper_parameters'])   # the run's own config
model = build_model(cfg, 259, 2048)              # 259 for byte targets (C5)
model.load_state_dict({k[6:]: v for k, v in ck['state_dict'].items()
                       if k.startswith('model.')})

build_model is not in this repo: the snippet needs the assignment's src/ on PYTHONPATH. data/bpe_plain.json is the exact BPE vocabulary these checkpoints were trained against, and data/splits/ is the train/test partition, so the numbers above are reproducible.

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