\n
\n setCompletionOnly((v) => !v)}\n style={{\n ...mono,\n padding: '5px 12px',\n borderRadius: 6,\n cursor: 'pointer',\n border: `1px solid ${completionOnly ? 'var(--accent)' : 'var(--line-2)'}`,\n background: completionOnly ? 'var(--accent-soft)' : 'transparent',\n color: completionOnly ? 'var(--accent)' : 'var(--ink-2)',\n }}\n >\n loss: {completionOnly ? 'completion-only (masked)' : 'all tokens (unmasked)'}\n \n \n scored on {scored} / {total} tokens\n \n
\n\n
prompt (the input — given)
\n
\n {PROMPT.map((tok, i) => (\n \n ))}\n
\n\n
completion (the target — always scored)
\n
\n {COMPLETION.map((tok, i) => (\n '} />\n ))}\n
\n\n
\n {completionOnly ? (\n <>\n Prompt tokens have label = −100 — seen as context, never scored. All {COMPLETION.length} completion tokens\n (including <eos> , so it learns to stop) drive the loss.\n >\n ) : (\n <>\n Every token is scored — so {100 - pct}% of the gradient is spent learning to regenerate the instruction , diluting the\n signal for the JSON you actually care about.\n >\n )}\n
\n
\n );\n}\n",
+ "frameTitle": "What actually gets scored",
+ "frameCaption": "SFT glues prompt + completion into one sequence and trains by next-token prediction. Toggle the loss: 'completion-only' masks the prompt (label = −100 — seen as context, never scored), so 100% of the signal trains the answer. 'all tokens' scores the prompt too — wasting most of the gradient teaching the model to regurgitate its own instructions.",
+ "frameSize": "normal",
+ "frameExpand": true
+ },
+ "children": []
+ },
+ {
+ "id": "paragraph-32",
+ "type": "paragraph",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Mechanism:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " alongside the tokens you build a ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "labels",
+ "styles": {
+ "code": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " array; masked positions get the sentinel ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "−100",
+ "styles": {
+ "code": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " (PyTorch’s ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "ignore_index",
+ "styles": {
+ "code": true
+ }
+ },
+ {
+ "type": "text",
+ "text": "), which contributes zero loss and zero direct gradient. The sequence loss is the average of cross-entropy over the ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "scored",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " positions only.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "paragraph-33",
+ "type": "paragraph",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Why:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " in fine-tuning you concatenate ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "[prompt][completion]",
+ "styles": {
+ "code": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " into one sequence. The prompt is the ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "input",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " — handed to the model for free at inference. You only want it to learn to produce the ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "completion",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": ". ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "Without masking:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " if the prompt is 50 tokens and the completion 10, ~83% of your gradient goes into learning to ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "regenerate the instruction text",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " — capacity spent on something you never need, diluting the signal for the actual answer. ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "What you get:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " every bit of learning signal aimed at the response.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "paragraph-34",
+ "type": "paragraph",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Two boundary facts everyone gets wrong at least once:",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "bulletListItem-35",
+ "type": "bulletListItem",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "The first completion token ",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": "is",
+ "styles": {
+ "bold": true,
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " scored.",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " The pair ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "(full prompt → first answer token)",
+ "styles": {
+ "code": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " is exactly “start the answer given the prompt” — the most important pair. Masking the prompt never means masking through the first completion token.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "bulletListItem-36",
+ "type": "bulletListItem",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "The EOS token ",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": "is",
+ "styles": {
+ "bold": true,
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " scored.",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " Score it or the model never learns to ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "stop",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " and rambles forever. Forgetting EOS is the classic loss-mask bug.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "paragraph-37",
+ "type": "paragraph",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "And a subtlety: masked-in-loss does ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "not",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " mean “no gradient at all.” The prompt tokens are still attended to, so gradient still flows into their representations via attention — the model learns to ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "represent",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " the prompt well, it just isn’t asked to ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "generate",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " it.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "quote-38",
+ "type": "quote",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "For the full mechanical deep-dive on this family specifically — the token-by-token ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "labels = −100",
+ "styles": {
+ "code": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " construction, multi-turn assistant masking, and whether masking saves compute — this is the one family with its own companion piece.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "heading-39",
+ "type": "heading",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left",
+ "level": 1,
+ "isToggleable": false
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Family 3 — HIDE: objective masks",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "paragraph-40",
+ "type": "paragraph",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Now the role of masking ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "flips completely.",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " In Families 1–2 the mask ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "hides",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " things from attention or loss. Here the mask ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "creates the task",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": ": you deliberately hide part of the input and train the model to reconstruct it. The mask ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "is",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " the supervision.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "customComponent-41",
+ "type": "customComponent",
+ "props": {
+ "componentName": "DiffusionUnmask",
+ "source": "import { useEffect, useState, type CSSProperties } from 'react';\n\nconst PROMPT = ['Convert', 'to', 'JSON', ':', 'Ava', ',', '41'];\n// target tokens + the diffusion step at which each is revealed (structure first,\n// values last — deliberately NOT left-to-right, to show parallel denoising).\nconst TARGET: { tok: string; step: number }[] = [\n { tok: '{', step: 1 },\n { tok: '\"name\"', step: 2 },\n { tok: ':', step: 3 },\n { tok: '\"Ava\"', step: 2 },\n { tok: ',', step: 4 },\n { tok: '\"age\"', step: 1 },\n { tok: ':', step: 3 },\n { tok: '41', step: 4 },\n { tok: '}', step: 1 },\n];\nconst STEPS = 4;\n\nconst mono: CSSProperties = { fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--ink-2)' };\n\nexport default function DiffusionUnmask() {\n const [step, setStep] = useState(0);\n const [playing, setPlaying] = useState(false);\n\n useEffect(() => {\n if (!playing) return;\n const id = setInterval(() => setStep((s) => (s >= STEPS ? s : s + 1)), 720);\n return () => clearInterval(id);\n }, [playing]);\n\n useEffect(() => {\n if (step >= STEPS) setPlaying(false);\n }, [step]);\n\n const revealed = TARGET.filter((t) => t.step <= step).length;\n\n return (\n \n
\n {\n if (step >= STEPS) setStep(0);\n setPlaying((p) => !p);\n }}\n style={{ ...mono, padding: '6px 16px', borderRadius: 6, cursor: 'pointer', border: '1px solid var(--accent)', background: 'var(--accent-soft)', color: 'var(--accent)' }}\n >\n {playing ? '❚❚ pause' : step >= STEPS ? '↻ replay' : '▶ denoise'}\n \n {\n setPlaying(false);\n setStep(0);\n }}\n style={{ ...mono, padding: '6px 12px', borderRadius: 6, cursor: 'pointer', border: '1px solid var(--line-2)', background: 'transparent', color: 'var(--ink-2)' }}\n >\n reset\n \n \n step {step} / {STEPS} · {revealed}/{TARGET.length} unmasked\n \n
\n\n
prompt (never masked)
\n
\n {PROMPT.map((tok, i) => (\n \n {tok}\n \n ))}\n
\n\n
completion (starts fully masked, unmasked in parallel)
\n
\n {TARGET.map((t, i) => {\n const shown = t.step <= step;\n return (\n \n {shown ? t.tok : '▨'}\n \n );\n })}\n
\n\n
\n A masked diffusion LM starts from an all-▨ completion and unmasks positions in parallel ,\n coarse-to-fine — not one token left-to-right. The prompt is held fixed the whole time (it is the part that is never masked).\n
\n
\n );\n}\n",
+ "frameTitle": "Masked diffusion: unmasking in parallel",
+ "frameCaption": "A diffusion LM (LLaDA, Gemini Diffusion) starts from an all-masked completion and reveals positions in parallel, coarse-to-fine — not one token left-to-right. The prompt is the part that is never masked. This is why Gemini Diffusion hits ~1,479 tok/s, roughly 5× a comparable autoregressive model: it decodes many positions per step.",
+ "frameSize": "normal",
+ "frameExpand": true
+ },
+ "children": []
+ },
+ {
+ "id": "heading-42",
+ "type": "heading",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left",
+ "level": 2,
+ "isToggleable": false
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Masked Language Modeling (BERT)",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "paragraph-43",
+ "type": "paragraph",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "What:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " randomly replace ~",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "15%",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " of tokens with ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "[MASK]",
+ "styles": {
+ "code": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " and train the model (bidirectionally) to predict the originals. ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "Why:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " it manufactures a supervised task from raw text while letting every token use both-side context. ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "The 80/10/10 wrinkle:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " of the chosen 15%, only 80% become ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "[MASK]",
+ "styles": {
+ "code": true
+ }
+ },
+ {
+ "type": "text",
+ "text": ", 10% become a random token, 10% are left unchanged — because ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "[MASK]",
+ "styles": {
+ "code": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " never appears at inference time, so training purely on it would create a train/serve mismatch. ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "What you get:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " strong bidirectional representations for understanding tasks.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "heading-44",
+ "type": "heading",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left",
+ "level": 2,
+ "isToggleable": false
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Span corruption (T5)",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "paragraph-45",
+ "type": "paragraph",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "What:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " mask contiguous ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "spans",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " (avg length ~3, ~15% of tokens), replace each with a single sentinel, and have the decoder emit the missing spans. UL2 generalizes this into a menu of denoisers (R = normal spans, S = prefix-LM, X = extreme/long spans). ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "Why:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " spans force the model to generate multi-token chunks, closer to real generation than single-token MLM.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "heading-46",
+ "type": "heading",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left",
+ "level": 2,
+ "isToggleable": false
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Masked diffusion LMs (the 2026 twist)",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "paragraph-47",
+ "type": "paragraph",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "What:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " the forward process masks a ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "random fraction",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "t ~ U[0,1]",
+ "styles": {
+ "code": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " of tokens; the reverse process learns to predict all masked tokens at once, and generation runs it iteratively — start fully masked, unmask in parallel over a handful of steps (the component above). ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "Why it’s exciting:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " decoding many positions per step instead of strictly one-at-a-time. ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "Gemini Diffusion",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " (Google, 2025) reported ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "~1,479 tokens/second — roughly 5× a comparable autoregressive model.",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " LLaDA showed the recipe scales to compete with strong AR baselines. Same masking primitive as BERT, aimed at generation instead of understanding.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "heading-48",
+ "type": "heading",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left",
+ "level": 2,
+ "isToggleable": false
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Masked autoencoders (vision, for contrast)",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "paragraph-49",
+ "type": "paragraph",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "What:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " hide ~",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "75%",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " of image patches and reconstruct them (MAE). It’s the same idea one modality over — proof that “hide input to create a task” is a general recipe, not a text trick.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "heading-50",
+ "type": "heading",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left",
+ "level": 1,
+ "isToggleable": false
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Family 4 — DROP: regularization masks",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "paragraph-51",
+ "type": "paragraph",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "The loosest use of the word, included so the field guide is complete. ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "Dropout",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " applies a ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "random",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " binary mask that zeroes a fraction of activations ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "during training only",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " (scaling the survivors to compensate). ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "Why:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " it stops neurons from co-adapting into fragile combinations, which reduces overfitting. ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "Key difference from the others:",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " it’s random, it’s for regularization, and it’s ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "off at inference",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " — the other three families are deterministic and structural. (DropPath / stochastic depth is the same idea applied to whole layers.)",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "heading-52",
+ "type": "heading",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left",
+ "level": 1,
+ "isToggleable": false
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "One token, five masks at once",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "paragraph-53",
+ "type": "paragraph",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Here’s the payoff — why the word felt so slippery. Take a single ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "completion token",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": ", sitting in a ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "packed, padded, multi-example SFT batch",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": ", and watch how many independent masks touch it simultaneously:",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "table-54",
+ "type": "table",
+ "props": {
+ "textColor": "default"
+ },
+ "content": {
+ "type": "tableContent",
+ "columnWidths": [
+ null,
+ null
+ ],
+ "rows": [
+ {
+ "cells": [
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "Mask",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "Effect on this one token",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ }
+ ]
+ },
+ {
+ "cells": [
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "causal",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " (SEE)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "may attend to earlier tokens in its own example",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ }
+ ]
+ },
+ {
+ "cells": [
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "document",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " (SEE)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "may ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "not",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " attend to the other packed example",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ }
+ ]
+ },
+ {
+ "cells": [
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "padding",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " (SEE)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "ignores the batch’s pad tokens",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ }
+ ]
+ },
+ {
+ "cells": [
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "loss / completion",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " (SCORE)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "it ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "is",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " scored (it’s part of the answer)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ }
+ ]
+ },
+ {
+ "cells": [
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "dropout",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " (DROP)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "some of its activations are randomly zeroed this step",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "children": []
+ },
+ {
+ "id": "paragraph-55",
+ "type": "paragraph",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Five separate gates on one token, spanning three of the four families (three SEE, one SCORE, one DROP) — and if it were a diffusion-LM token instead of an SFT one, HIDE would make it all four. Nobody was ever confused about ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "one",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " thing called masking — they were quietly conflating a fistful of them.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "heading-56",
+ "type": "heading",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left",
+ "level": 1,
+ "isToggleable": false
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Which model uses which",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "table-57",
+ "type": "table",
+ "props": {
+ "textColor": "default"
+ },
+ "content": {
+ "type": "tableContent",
+ "columnWidths": [
+ null,
+ null,
+ null,
+ null
+ ],
+ "rows": [
+ {
+ "cells": [
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "Model family",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "Attention shape",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "Objective mask",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "Loss mask (if fine-tuned)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ }
+ ]
+ },
+ {
+ "cells": [
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "Decoder-only (GPT, Llama, Qwen)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "causal (+ window / packing)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "none (next-token)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "completion-only",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ }
+ ]
+ },
+ {
+ "cells": [
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "Encoder (BERT)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "bidirectional",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "MLM (15%, 80/10/10)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "—",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ }
+ ]
+ },
+ {
+ "cells": [
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "Encoder–decoder (T5)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "enc: bidirectional · dec: causal",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "span corruption",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "target-side",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ }
+ ]
+ },
+ {
+ "cells": [
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "Diffusion LM (LLaDA, Gemini Diffusion)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "bidirectional",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "masked diffusion (",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "t ~ U[0,1]",
+ "styles": {
+ "code": true
+ }
+ },
+ {
+ "type": "text",
+ "text": ")",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "completion-only",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ }
+ ]
+ },
+ {
+ "cells": [
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "Vision (ViT / MAE)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "bidirectional",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "patch masking (~75%)",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ },
+ {
+ "type": "tableCell",
+ "content": [
+ {
+ "type": "text",
+ "text": "—",
+ "styles": {}
+ }
+ ],
+ "props": {
+ "colspan": 1,
+ "rowspan": 1,
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "children": []
+ },
+ {
+ "id": "heading-58",
+ "type": "heading",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left",
+ "level": 1,
+ "isToggleable": false
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Gotchas & confusions",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "paragraph-59",
+ "type": "paragraph",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "The traps, collected — most of these are silent (no error, just worse results):",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "bulletListItem-60",
+ "type": "bulletListItem",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Attention mask ≠ loss mask ≠ MLM mask.",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " The single biggest confusion. They gate different things (what you ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "see",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " vs what you’re ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "scored on",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " vs what’s ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "hidden to learn",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": "). Always ask which family.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "bulletListItem-61",
+ "type": "bulletListItem",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Masked ≠ hidden, masked ≠ no-gradient.",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " A loss-masked prompt token is still seen (attention) and still gets gradient through attention — it’s just not a prediction ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "target",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": ".",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "bulletListItem-62",
+ "type": "bulletListItem",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Forget to score EOS → the model never stops.",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " Include the end token in the completion loss.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "bulletListItem-63",
+ "type": "bulletListItem",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Don’t mask through the first completion token",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " — that transition (prompt → first answer token) is the most important thing to learn.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "bulletListItem-64",
+ "type": "bulletListItem",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Packing without a document mask → silent cross-contamination.",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " Looks like a free speedup; actually teaches the model that unrelated examples are each other’s context.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "bulletListItem-65",
+ "type": "bulletListItem",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Padding side matters.",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " For causal decoders you typically ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "left-pad",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " at generation time (so the real last token is at the true end and positions line up), while training often right-pads. Mixing them up produces garbage or misaligned outputs.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "bulletListItem-66",
+ "type": "bulletListItem",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[MASK]",
+ "styles": {
+ "code": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " train/serve mismatch",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " — the reason for BERT’s 80/10/10: the mask token never appears at inference, so you can’t train exclusively on it.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "bulletListItem-67",
+ "type": "bulletListItem",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Don’t compare masked vs unmasked loss values.",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " Different denominators (different token counts) — the numbers aren’t on the same scale.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "bulletListItem-68",
+ "type": "bulletListItem",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Masking doesn’t save transformer compute.",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " Completion-only loss skips only the tiny cross-entropy at masked positions; the full sequence still runs through every layer. Masking is about ",
+ "styles": {}
+ },
+ {
+ "type": "text",
+ "text": "signal quality",
+ "styles": {
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": ", not speed. (The real cost lever is not paying for prompt tokens you don’t train on — hence packing.)",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "bulletListItem-69",
+ "type": "bulletListItem",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Dropout is training-only.",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " Leaving it on at inference makes outputs noisy and non-deterministic.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "heading-70",
+ "type": "heading",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left",
+ "level": 1,
+ "isToggleable": false
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "The one-line mental model",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "quote-71",
+ "type": "quote",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "A mask is a 0/1 gate. When you meet one, don’t ask “what’s a mask?” — ask “ignore ",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": "what",
+ "styles": {
+ "bold": true,
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": ", for ",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": "what purpose",
+ "styles": {
+ "bold": true,
+ "italic": true
+ }
+ },
+ {
+ "type": "text",
+ "text": "?”",
+ "styles": {
+ "bold": true
+ }
+ },
+ {
+ "type": "text",
+ "text": " The answer lands it in one of four families, and everything else follows.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ },
+ {
+ "id": "paragraph-72",
+ "type": "paragraph",
+ "props": {
+ "backgroundColor": "default",
+ "textColor": "default",
+ "textAlignment": "left"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Get that reflex and every mask in every paper — causal, padding, block-diagonal, MLM, diffusion, dropout — is just a different answer to the same two questions.",
+ "styles": {}
+ }
+ ],
+ "children": []
+ }
+ ],
+ "tableVariants": {}
+}
diff --git a/src/content/posts/masks-in-transformers/index.mdx b/src/content/posts/masks-in-transformers/index.mdx
index e4785ee..7f2c227 100644
--- a/src/content/posts/masks-in-transformers/index.mdx
+++ b/src/content/posts/masks-in-transformers/index.mdx
@@ -3,32 +3,33 @@ title: 'Every Mask in a Transformer, Untangled'
summary: 'The word "mask" means at least four unrelated things in deep learning — what a token can see, what counts toward the loss, what is hidden to create a task, and what is randomly dropped. One field guide to all of them, with why each exists and what breaks without it.'
authors: ['dinesh']
date: '2026-07-20'
-readMin: 18
+updated: '2026-07-20'
+readMin: 9
topic: 'Training'
topicId: 'training'
tags: ['masking', 'attention', 'transformers', 'causal-mask', 'bert', 'diffusion-llm', 'fine-tuning']
---
-import Interactive from '../../../components/Interactive';
import AttentionMaskExplorer from './AttentionMaskExplorer';
+import Interactive from '../../../components/Interactive';
import LossMaskStrip from './LossMaskStrip';
import DiffusionUnmask from './DiffusionUnmask';
If you read enough about transformers, you hit the word **mask** everywhere — causal mask, padding mask, attention mask, loss mask, masked language modeling, masked diffusion — and it quietly starts to feel like one slippery concept you never quite pinned down.
-Here's the secret: it isn't one concept. **"Mask" names at least four completely unrelated mechanisms.** A single token, in a single training step, can be masked in several different senses *at once*, and they have nothing to do with each other. That overloading is the entire source of the confusion.
+Here’s the secret: it isn’t one concept. **“Mask” names at least four completely unrelated mechanisms.** A single token, in a single training step, can be masked in several different senses _at once_, and they have nothing to do with each other. That overloading is the entire source of the confusion.
-This post untangles all of them: what each mask is, **why** it exists, what you **get** from it, and — the part most explanations skip — **what breaks if you don't use it.** By the end, "mask" should never be a fog word again.
+This post untangles all of them: what each mask is, **why** it exists, what you **get** from it, and — the part most explanations skip — **what breaks if you don’t use it.** By the end, “mask” should never be a fog word again.
## What a mask actually is
Strip away the jargon and every mask is the same primitive:
-