Feature Extraction
Transformers
Safetensors
English
tridlm
masked-diffusion
diffusion-language-model
gpt2
openwebtext
triangular-attention
custom_code
Instructions to use EER6/TriDLM-124M-split with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use EER6/TriDLM-124M-split with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("feature-extraction", model="EER6/TriDLM-124M-split", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("EER6/TriDLM-124M-split", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
|
Download README.md from EER6/TriDLM-124M-split: direct link, hf CLI and curl.
- Browser
- Download file 4.6 kB
-
https://huggingface.co/EER6/TriDLM-124M-split/resolve/main/README.md
- Command line
-
hf download hf://EER6/TriDLM-124M-split/README.md
-
curl -L -o README.md https://huggingface.co/EER6/TriDLM-124M-split/resolve/main/README.md
4.6 kB
| license: apache-2.0 | |
| language: en | |
| library_name: transformers | |
| tags: [masked-diffusion, diffusion-language-model, gpt2, openwebtext, triangular-attention] | |
| datasets: [Skylion007/openwebtext] | |
| # TriDLM-124M-split | |
| A 124M-parameter **masked-diffusion language model** (MDLM-style absorbing-state denoiser) with **every layer: even heads causal, odd heads anti-causal**, one of four arms of the | |
| TriDLM experiment: can a diffusion LM keep its quality when every attention head is *triangular* (causal or anti-causal), so that | |
| attention costs ~L²/2 instead of L²? Code, training logs and the full experiment record: https://github.com/AntonXue/TriDLM (`_claude/`). | |
| ## The four arms (identical model, data order, masks and recipe; only the per-head attention mask differs) | |
| | repo | attention | val NELBO (nats/token) | ppl | train tok/s (8×GH200) | | |
| |---|---|---|---|---| | |
| | `EER6/TriDLM-124M-bidir` | all heads bidirectional (the stock MDLM control) | 3.374 | 29.2 | 2.60M | | |
| | `EER6/TriDLM-124M-split` | every layer: even heads causal, odd heads anti-causal | 3.395 | 29.8 | 2.73M | | |
| | `EER6/TriDLM-124M-alt` | even layers all-causal, odd layers all-anti-causal | 3.406 | 30.2 | 2.55M | | |
| | `EER6/TriDLM-124M-causal` | all heads causal (lower-bound control) | 4.940 | 139.7 | 2.73M | | |
| NELBO = the exact-count masked-diffusion ELBO (equal in expectation to the MDLM 1/t objective) on all 110,451 OWT-validation blocks. | |
| `split` trails `bidir` by 0.020 nats (~2 % ppl) and `alt` by 0.032; `causal` (no right context) is the expected lower bound. | |
| Generation metrics (gen-ppl under gpt2-large, MAUVE-256) per sampler and prompting condition are in the GitHub record. | |
| ## Model | |
| GPT-2-small denoiser ported from nanoGPT (12 layers, 768 d, 12 heads, learned absolute positions, LayerNorm without bias, GELU, | |
| tied embeddings), vocab 50304 = gpt2's 50257 + `[MASK]` (id 50257) + pads, **no next-token shift: position i predicts token i**, and | |
| **per-head QK-norm** (LayerNorm on q and k over the head dim). QK-norm is essential: without it every triangular arm diverged from | |
| attention-logit growth (max |q·k/√d| in layers 1–3 grew from ~40 to 10⁶ by 25–30k steps at both lr 3e-4 and 1e-4, while the | |
| bidirectional arm stayed at ~42); with it all four arms train cleanly. | |
| ## Training | |
| OpenWebText (gpt2 BPE, 1024-token packed blocks with EOS separators), **100k steps × 512 × 1024 = 52.4B tokens** (5.9 epochs), | |
| AdamW lr 1e-4 (β 0.9/0.95, wd 0.1, clip 1.0), warmup 1000 → 89,000 stable → 10,000 cosine decay to 0, bf16, seed 1. Loss = mean over | |
| rows of the mean cross-entropy over the masked positions of each row, with the mask count n ~ U{1..L} stratified across the batch | |
| and the mask set a uniform n-subset; `[MASK]`/pad logits are −∞ (SUBS). Trained on 8 GH200 nodes (1 GPU each) in ~5.5 h. | |
| ## Usage | |
| ```python | |
| import torch | |
| from transformers import AutoModel, AutoTokenizer | |
| tok = AutoTokenizer.from_pretrained("EER6/TriDLM-124M-split") # gpt2 BPE + [MASK] = 50257 | |
| model = AutoModel.from_pretrained("EER6/TriDLM-124M-split", trust_remote_code=True, attn_impl="sdpa").cuda().eval() | |
| # attn_impl="sdpa": dense masks, any torch >= 2.1; "flex" (block-sparse, needs torch >= 2.5 + Triton) is numerically identical. | |
| x0 = tok("The quick brown fox", return_tensors="pt")["input_ids"].cuda() # (B, L <= 1024) | |
| mask = torch.rand(x0.shape, device=x0.device) < 0.5 | |
| xt = torch.where(mask, torch.full_like(x0, tok.mask_token_id), x0) | |
| logits = model(xt).logits # (B, L, 50304); position i predicts token i | |
| logits[..., 50257:] = float("-inf") # SUBS: never predict [MASK] or pads | |
| ``` | |
| Sampling: use the random-order ancestral sampler (`eval.py: ancestral_sample`) — gen-ppl 56 ± 3 under gpt2-large at NFE 1024 for | |
| `bidir`. Confidence-ordered decoding (argmax *or* sampled tokens, threshold or one-at-a-time) collapses into repetition on these | |
| base models; MAUVE catches it. The `causal`/`split`/`alt` checkpoints must be evaluated through their own `attn_mode` (saved in | |
| the config); never run them with a full mask. | |
| ## Notes | |
| - The training set (mdlm-vibes' OWT prep) contains one block with a stray `[MASK]` id; it makes one logged loss value `inf` per epoch | |
| and has no effect on the gradients. | |
| - No EMA; the final checkpoint is the post-decay endpoint. The end-of-stable-phase full checkpoint (step 90k, optimizer included) is | |
| kept offline for WSD extensions. | |
| - Ported model code (MIT, nanoGPT) is included as `modeling_tridlm.py`; this repo is apache-2.0. | |