{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# **A2D2 Unmasking + Insertion Quality Inference on a Toy Example**\n", "\n", "This notebook is a self-contained, runnable illustration of the two quantities at the heart of **A2D2: Fine-Tuning Any-Length Discrete Diffusion for Adaptive Decoding**, and how they are used at *inference* time to decode adaptively:\n", "\n", "| Quantity | Definition | Inference use |\n", "|---|---|---|\n", "| **Unmasking quality** $\\mu_\\star^\\ell(\\boldsymbol{y})=p(\\boldsymbol{y}^\\ell=\\boldsymbol{x}_1^{s_t[\\ell]}\\mid \\boldsymbol{y})=f_\\theta(\\tilde{\\boldsymbol{x}}_t,t)[\\ell,\\boldsymbol{x}_1^\\ell]$ | probability an unmasked token matches the true token given context | **re-mask** low-quality tokens so only mutually high-quality tokens stay unmasked in parallel |\n", "| **Insertion quality** $\\nu_\\star^\\ell(\\boldsymbol{y})=\\sum_{\\boldsymbol{v}\\in\\mathcal{S}_\\ell}p(\\boldsymbol{y}^\\ell=\\boldsymbol{v}\\mid \\boldsymbol{y})$ | probability an inserted mask decodes to *some* true token belonging in its gap | **drop** low-quality insertions that would otherwise cause length/spacing errors |\n", "\n", "In this notebook, we build a tiny, fully-analytic **toy \"language\"** whose true denoising posterior $f_\\theta$ is known in closed form. That lets us (1) compute $\\mu_\\star,\\nu_\\star$ exactly, (2) train the light-weight predictors $\\mu_\\phi,\\nu_\\phi$ with the paper's **UQL/IQL** BCE losses and watch them recover the truth, and (3) drive the **actual** A2D2 inference routines `apply_schedule_aware_remasking` / `apply_schedule_aware_insertion` (from `remasking_scheduleaware.py`) on hand-crafted states." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 0. Setup\n", "\n", "The two schedule-aware routines below are from the repo's `remasking_scheduleaware.py`. They are the exact code the A2D2 sampler calls. We only feed them a tiny toy `model` exposing the same interface (`model.planner(seq, t)` → confidences, `model.interpolant.{unmask,insertion}_schedule.at(t)`)." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import torch\n", "import torch.nn as nn\n", "import torch.nn.functional as F\n", "import matplotlib.pyplot as plt\n", "\n", "torch.manual_seed(0)\n", "np.random.seed(0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "vendored A2D2 schedule-aware routines loaded\n" ] } ], "source": [ "def _debias_by_token(conf, tokens, clean_index):\n", " \"\"\"Subtract the per-token-identity mean confidence so a token's score reflects\n", " how confident it is RELATIVE to others of the same type (see repo docstring).\"\"\"\n", " if clean_index.sum() == 0:\n", " return conf\n", " V = int(tokens.max().item()) + 1\n", " flat_tok = tokens[clean_index]\n", " flat_conf = conf[clean_index]\n", " sums = torch.zeros(V, device=conf.device, dtype=conf.dtype).scatter_add_(0, flat_tok, flat_conf)\n", " cnts = torch.zeros(V, device=conf.device, dtype=conf.dtype).scatter_add_(\n", " 0, flat_tok, torch.ones_like(flat_conf))\n", " mean_v = sums / cnts.clamp(min=1.0)\n", " baseline = mean_v[tokens]\n", " return torch.where(clean_index, conf - baseline, conf)\n", "\n", "\n", "def apply_schedule_aware_insertion(model, xt_tmp, new_xt, t, dt, ext, mask, pad,\n", " max_length, orig_mask, new_pos_orig, quality_threshold=1):\n", " \"\"\"Remove low-quality insertions (insertion_conf < threshold) while keeping the\n", " sequence length no shorter than the interpolant schedule allows.\"\"\"\n", " device = xt_tmp.device\n", " batch_size, L = xt_tmp.shape\n", " total_ext = ext.sum(dim=1)\n", " if total_ext.sum() == 0:\n", " return xt_tmp\n", "\n", " t_next = t + dt\n", " planner_out = model.planner(xt_tmp, t)\n", " insertion_conf = planner_out.get(\"insertion_conf\", None)\n", " if insertion_conf is None:\n", " return xt_tmp\n", " insertion_conf = insertion_conf.squeeze(-1) # (B, L)\n", "\n", " current_length_after = xt_tmp.ne(pad).sum(dim=1).float()\n", " expected_progress = model.interpolant.insertion_schedule.at(t_next)\n", " estimated_final_length = current_length_after / (expected_progress.clamp(min=0.1))\n", " expected_length = estimated_final_length * expected_progress\n", "\n", " valid_b, valid_l = orig_mask.nonzero(as_tuple=True)\n", " valid_p = new_pos_orig[valid_b, valid_l].long().clamp_(0, L - 1)\n", " is_original = torch.zeros_like(xt_tmp, dtype=torch.bool)\n", " is_original[valid_b, valid_p] = True\n", " inserted_positions = (xt_tmp == mask) & ~is_original\n", "\n", " candidates = inserted_positions & (insertion_conf < quality_threshold)\n", " num_bad = candidates.sum(dim=1)\n", " min_length = expected_length.long().clamp(min=1)\n", " max_removable = (current_length_after.long() - min_length).clamp(min=0)\n", " length_after_removal = current_length_after.long() - num_bad\n", " schedule_violates = length_after_removal < min_length\n", " k_per_row = torch.where(schedule_violates, max_removable, num_bad)\n", " k_per_row = torch.where(num_bad > 0, k_per_row, torch.zeros_like(k_per_row))\n", "\n", " if not candidates.any():\n", " return xt_tmp\n", "\n", " neg_inf = torch.tensor(float('-inf'), device=device, dtype=insertion_conf.dtype)\n", " scores = torch.where(candidates, -insertion_conf, neg_inf)\n", " _, sorted_indices = scores.sort(dim=1, descending=True)\n", " positions = torch.arange(L, device=device).unsqueeze(0)\n", " keep_in_topk = positions < k_per_row.unsqueeze(1)\n", " final_bad = torch.zeros_like(candidates)\n", " final_bad.scatter_(1, sorted_indices, keep_in_topk)\n", " if not final_bad.any():\n", " return xt_tmp\n", "\n", " sort_key = final_bad.long()\n", " _, perm = torch.sort(sort_key, dim=1, stable=True)\n", " xt_tmp = torch.gather(xt_tmp, 1, perm)\n", " num_keep = (~final_bad).sum(dim=1)\n", " tail_mask = positions >= num_keep.unsqueeze(1)\n", " xt_tmp = torch.where(tail_mask, torch.full_like(xt_tmp, pad), xt_tmp)\n", " return xt_tmp\n", "\n", "\n", "def apply_schedule_aware_remasking(model, new_xt, t, dt, remasking_conf, clean_index,\n", " mask, neg_inf, batch_size, debias=False):\n", " \"\"\"Re-mask the lowest-confidence clean tokens so the unmasked count tracks the\n", " unmask schedule (FlexMDM-style schedule-aware remasking).\"\"\"\n", " t_next = t + dt\n", " num_clean = clean_index.sum(dim=1)\n", " current_seq_len = (num_clean + (new_xt == mask).sum(dim=1)).float()\n", " expected_unmasked_frac = model.interpolant.unmask_schedule.at(t_next)\n", " expected_num_clean = expected_unmasked_frac * current_seq_len\n", " masks_to_add = (num_clean.float() - expected_num_clean).round().long()\n", "\n", " k_per_row = torch.minimum(masks_to_add.clamp(min=0), num_clean)\n", " if k_per_row.sum() == 0:\n", " return new_xt\n", "\n", " conf = _debias_by_token(remasking_conf, new_xt, clean_index) if debias else remasking_conf\n", " remasking_score_temp = -1.0 * conf\n", " remasking_score_temp = torch.where(clean_index, remasking_score_temp, neg_inf)\n", " _, sorted_indices = remasking_score_temp.sort(dim=1, descending=True)\n", " L = remasking_score_temp.shape[1]\n", " positions = torch.arange(L, device=new_xt.device).unsqueeze(0)\n", " keep_in_topk = positions < k_per_row.unsqueeze(1)\n", " to_mask = torch.zeros_like(clean_index)\n", " to_mask.scatter_(1, sorted_indices, keep_in_topk)\n", " new_xt = torch.where(to_mask, torch.full_like(new_xt, mask), new_xt)\n", " return new_xt\n", "\n", "print(\"vendored A2D2 schedule-aware routines loaded\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. A toy \"language\" with a known denoising posterior $f_\\theta$\n", "\n", "A real any-length MDM parameterizes an **unmasking posterior** $f_\\theta(\\boldsymbol{x}_t,t)[\\ell]\\in\\Delta^V$. Here we replace it with an analytic stand-in: a 5-letter **bigram** model with a peaked transition matrix $T$. Given a partially-masked sequence, the posterior at a masked position is the (normalized) product of the constraints from its clean left/right neighbours, which is exactly the kind of context-dependent posterior $f_\\theta$ learns, but in closed form so we know $\\mu_\\star,\\nu_\\star$ exactly.\n", "\n", "Special tokens: `MASK` and `PAD` (matching the sampler's two reserved ids)." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a clean target x1 : BCDEABCDEA\n", "posterior at a masked middle position (neighbours clean):\n", " state: BCDEA_CDEA f_theta[5] = [0.009 0.963 0.009 0.009 0.009]\n" ] } ], "source": [ "LETTERS = [\"A\", \"B\", \"C\", \"D\", \"E\"]\n", "V = len(LETTERS)\n", "MASK, PAD = V, V + 1 # reserved ids, as in the sampler\n", "NTOK = V + 2\n", "\n", "# Peaked bigram transition matrix -> context is informative.\n", "T = np.array([\n", " [0.05, 0.70, 0.10, 0.10, 0.05], # A -> mostly B\n", " [0.05, 0.05, 0.75, 0.10, 0.05], # B -> mostly C\n", " [0.10, 0.05, 0.05, 0.70, 0.10], # C -> mostly D\n", " [0.10, 0.10, 0.05, 0.05, 0.70], # D -> mostly E\n", " [0.70, 0.05, 0.10, 0.10, 0.05], # E -> mostly A\n", "], dtype=np.float64)\n", "T /= T.sum(1, keepdims=True)\n", "pi0 = np.array([0.4, 0.2, 0.2, 0.1, 0.1]) # initial-token distribution\n", "\n", "def sample_seq(n):\n", " \"\"\"Draw a clean sequence x_1 ~ p_target from the bigram chain.\"\"\"\n", " s = [np.random.choice(V, p=pi0)]\n", " for _ in range(n - 1):\n", " s.append(np.random.choice(V, p=T[s[-1]]))\n", " return s\n", "\n", "def posterior_at(seq, ell):\n", " \"\"\"Toy f_theta(seq, t)[ell] in Delta^V: bigram constraints from clean neighbours.\"\"\"\n", " factor = np.ones(V)\n", " if ell - 1 >= 0 and seq[ell - 1] < V: # clean left neighbour a -> T[a, :]\n", " factor *= T[seq[ell - 1], :]\n", " if ell + 1 < len(seq) and seq[ell + 1] < V: # clean right neighbour c -> T[:, c]\n", " factor *= T[:, seq[ell + 1]]\n", " if factor.sum() == 0:\n", " factor = np.ones(V)\n", " return factor / factor.sum()\n", "\n", "def decode(seq):\n", " return \"\".join(\"_\" if t == MASK else (\".\" if t == PAD else LETTERS[t]) for t in seq)\n", "\n", "x1 = sample_seq(10)\n", "print(\"a clean target x1 :\", decode(x1))\n", "print(\"posterior at a masked middle position (neighbours clean):\")\n", "probe = x1.copy(); probe[5] = MASK\n", "print(\" state:\", decode(probe), \" f_theta[5] =\", np.round(posterior_at(probe, 5), 3))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Unmasking quality $\\mu_\\star$\n", "\n", "Given a clean target $\\boldsymbol{x}_1$, an interpolant sample $\\tilde{\\boldsymbol{x}}_t$ (partially masked), and a candidate unmasking $\\boldsymbol{y}$ with $\\boldsymbol{y}^\\ell \\sim f_\\theta(\\tilde{\\boldsymbol{x}}_t,t)[\\ell]$, the **unmasking quality** is the posterior probability of the *true* token:\n", "\n", "$$\\mu_\\star^\\ell(\\boldsymbol{y}) = p\\!\\left(\\boldsymbol{y}^\\ell=\\boldsymbol{x}_1^{s_t[\\ell]}\\mid \\boldsymbol{y}\\right)=f_\\theta(\\tilde{\\boldsymbol{x}}_t,t)[\\ell,\\boldsymbol{x}_1^\\ell]$$\n", "\n", "High when the context pins down the token; low when it doesn't. Below, the middle masked position (both neighbours clean) is high-quality, while an isolated masked position (no clean neighbours) has a near-uniform posterior → low quality." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "clean x1 : CDEDABAC\n", "masked x~t: C_ED_B_C\n", "masked isolated: ___DABAC\n", "\n", " pos 1: true D mu* = 0.966 posterior=[0.01 0. 0.01 0.97 0.01]\n", " pos 4: true A mu* = 0.596 posterior=[0.6 0.04 0.02 0.04 0.3 ]\n", " pos 6: true A mu* = 0.056 posterior=[0.06 0.42 0.42 0.06 0.06]\n", " isolated pos 1: true D mu* = 0.200 (near-uniform -> low quality)\n" ] } ], "source": [ "x1 = sample_seq(8)\n", "xt = x1.copy()\n", "for ell in [1, 4, 6]:\n", " xt[ell] = MASK\n", "print(\"clean x1 :\", decode(x1))\n", "print(\"masked x~t:\", decode(xt))\n", "print(\"masked isolated: \", end=\"\")\n", "iso = [MASK if i in (0, 1, 2) else x1[i] for i in range(len(x1))] # left token has no clean nbrs\n", "print(decode(iso))\n", "print()\n", "for ell in [1, 4, 6]:\n", " p = posterior_at(xt, ell)\n", " print(f\" pos {ell}: true {LETTERS[x1[ell]]} mu* = {p[x1[ell]]:.3f} posterior={np.round(p,2)}\")\n", "p_iso = posterior_at(iso, 1)\n", "print(f\" isolated pos 1: true {LETTERS[x1[1]]} mu* = {p_iso[x1[1]]:.3f} (near-uniform -> low quality)\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.1 Training the unmasking-quality predictor $\\mu_\\phi$ (UQL)\n", "\n", "At inference we have no $\\boldsymbol{x}_1$, so A2D2 trains a light head $\\mu_\\phi$ to predict quality from the *post-unmasking* sequence $\\boldsymbol{y}$ alone, via the **Unmasking Quality Loss** (binary cross-entropy against the 0/1 hit indicator):\n", "\n", "$$\\mathcal{L}_{\\text{UQL}}(\\phi)=\\mathbb{E}\\Big[\\textstyle\\sum_{\\ell\\in\\mathcal{M}}\\text{BCE}\\big(\\mathbf{1}[\\boldsymbol{y}^\\ell=\\boldsymbol{x}_1^{s_t[\\ell]}],\\,\\mu_\\phi^\\ell(\\boldsymbol{y})\\big)\\Big].$$\n", "\n", "The unique minimizer is the true quality: $\\mu_{\\phi^\\star}=\\mu_\\star$. Note the head sees the *still-masked* neighbours (the realistic decode state), so the BCE minimizer is $P(\\text{correct}\\mid \\boldsymbol{y}) = f_\\theta(\\cdot)[\\ell,\\boldsymbol{y}^\\ell]$. We verify $\\mu_\\phi$ recovers it." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " step 500 UQL running avg = 0.5410 (irreducible floor = 0.4777)\n", " step 1000 UQL running avg = 0.4752 (irreducible floor = 0.4777)\n", " step 1500 UQL running avg = 0.4573 (irreducible floor = 0.4777)\n", " step 2000 UQL running avg = 0.4625 (irreducible floor = 0.4777)\n", "\n", "running loss 0.4625 sits at the floor 0.4777 -> converged\n", "corr(mu_phi, mu_star) on held-out states = 0.959\n" ] } ], "source": [ "WIN = 2 # context window (each side) fed to the head\n", "\n", "def window_feat(seq, ell):\n", " feats = []\n", " for d in range(-WIN, WIN + 1):\n", " j = ell + d\n", " tok = seq[j] if 0 <= j < len(seq) else PAD\n", " feats.append(F.one_hot(torch.tensor(tok), NTOK).float())\n", " return torch.cat(feats)\n", "\n", "def make_unmask_example():\n", " n = np.random.randint(6, 11)\n", " x1 = sample_seq(n)\n", " ctx = x1.copy()\n", " for i in range(n): # interpolant: mask ~half the tokens\n", " if np.random.rand() < 0.5:\n", " ctx[i] = MASK\n", " ell = np.random.randint(n)\n", " p = posterior_at(ctx, ell)\n", " samp = int(np.random.choice(V, p=p)) # y^ell ~ f_theta(ctx)[ell]\n", " y = ctx.copy(); y[ell] = samp # predictor sees still-masked neighbours\n", " label = float(samp == x1[ell]) # 1[y^ell == x_1]\n", " return window_feat(y, ell), torch.tensor([label]), p[samp] # p[samp] = true quality of y\n", "\n", "class QualityHead(nn.Module):\n", " def __init__(self, din):\n", " super().__init__()\n", " self.net = nn.Sequential(nn.Linear(din, 64), nn.GELU(), nn.Linear(64, 1))\n", " def forward(self, x):\n", " return torch.sigmoid(self.net(x))\n", " \n", "din = (2 * WIN + 1) * NTOK\n", "\n", "\"\"\"\n", "The UQL label 1[y^l == x_1] is a coin flip with probability mu_star, so even a PERFECT\n", "mu_phi cannot beat the entropy floor E[H(mu_star)]. The per-batch loss is also noisy\n", "(a fresh random minibatch each step), so we report an EMA-smoothed running loss + the floor. \n", "\n", "Convergence means the running loss sits AT the floor, not that it reaches 0\n", "\"\"\" \n", "_, _, q_pool = zip(*[make_unmask_example() for _ in range(4000)])\n", "uql_floor = binary_entropy(q_pool)\n", "\n", "mu_phi = QualityHead(din)\n", "opt = torch.optim.Adam(mu_phi.parameters(), lr=2e-3)\n", "run = None\n", "for step in range(2000):\n", " feats, labels, _ = zip(*[make_unmask_example() for _ in range(64)])\n", " loss = F.binary_cross_entropy(mu_phi(torch.stack(feats)), torch.stack(labels))\n", " opt.zero_grad(); loss.backward(); opt.step()\n", " run = loss.item() if run is None else 0.98 * run + 0.02 * loss.item()\n", " if (step + 1) % 500 == 0:\n", " print(f\" step {step+1:4d} UQL running avg = {run:.4f}\")\n", "\n", "with torch.no_grad():\n", " fs, _, qs = zip(*[make_unmask_example() for _ in range(800)])\n", " pred = mu_phi(torch.stack(fs)).squeeze(-1).numpy()\n", "qs = np.array(qs)\n", "print(f\"corr(mu_phi, mu_star) on held-out states = {np.corrcoef(pred, qs)[0,1]:.3f}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/png": "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dozffvuNPXv2APnzgd15553s27ePw4cPYzabbSuVPvroozzzzDP8+++/PP/88+zfv7/UPB4/fpzx48dz9OhRunTpwr333suCBQs4ceIEKpWKVatWATB//nzc3NzYt28fhw4domXLlrz55psA9OnTh7179xIVFcXGjRsZN26cbRGyG92fINzMduzYQe/evWkZFs5ybVM85aWUGSSwXE0kb++R6s3gNaIkUwEynZbwi7+X+nnunsPEP/zSDdMJWj0fly5tS71GeYwbNw7IX5fljjvuYOfOnYwYMaLYcQXrzvj7+9OgQQOio6MJDQ0FYPjw4SgUClxcXIiIiOD8+fN06dKFjRs3snfvXhYsWJB/X7m5qNVqMjMzOXbsGI8++igAnTt3pnXr1qXmsWnTpkRERADQvn17Ll26RJ06dQCIjIzkwoULQP4aMJmZmaxfvx7In96/YcOGQH5d8yOPPMKVK1dQKpUkJydz6dIlGjVqdMP7E4Sb2cqVK+nUqRPfjHmBnBduvGS5OSGlGnJVnAgyFSCTycqsytLdfRuKEH8scUklt8vIQBESgO7u2+xebC2tL3xJ687c6LPS1mTJzMysUJ/7oukX3S7ooCBJEosXL7YtH3C94cOH8+677/LAAw8A4OPjU6iKrqz7E4SbUXp6Ol5eXnz88cf560gdPElOOc5TBpa+9IkjieoyO5IpFPj974VrG0U/zP+P36wJdgkwy5YtA+DixYv8/fff3HHHHVVOs0Bpa7J4eHjQqlUrVq5cCeSvH3P06FG7XG/hwoXo9Xogf82L48eP265dv359AL755hvS0tKqfD1BqK2+//576tevz6FDh1AqlWi1Wswp6WWfJANFaADazm2qJY9FiSBjZ24DuhO4bBaKYP9C+xUhAQQum2W3cTIajYbbb7+d3r178+GHH9p1dbvS1mQBWLFiBR999BHt27fn008/pVOnTlW+3tSpU4mIiKBTp060adOGzp0721b3fP/99xk0aBB33HEHhw8fLnPdG0G4ma1Zs4YhQ4Zw77330rJlSyRJIn3xGhLH5bdfSkDRUTEFFSr2ermtDKdbT6am2Hs9GTHiv/YR68kIzuqrr75izJgxjBw5kmXLliGXJJJffZ/M5RsB8Bg9iBOhYegWLcMnO9N2nt7Hm/AFLzpkEHitXU/mZiFTKHC5vV1NZ0MQhFouOzubV199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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# predicted quality vs. true quality mu_star\n", "plt.figure(figsize=(4.2, 4.2))\n", "plt.scatter(qs, pred, s=6, alpha=0.25, label=\"held-out states\")\n", "bins = np.linspace(0, 1, 11)\n", "idx = np.digitize(qs, bins) - 1\n", "bx = [qs[idx == b].mean() for b in range(10) if (idx == b).any()]\n", "by = [pred[idx == b].mean() for b in range(10) if (idx == b).any()]\n", "plt.plot(bx, by, \"o-\", color=\"crimson\", label=\"binned mean\")\n", "plt.plot([0, 1], [0, 1], \"k--\", lw=1, label=\"ideal\")\n", "plt.xlabel(r\"true unmasking quality $\\mu_\\star$\")\n", "plt.ylabel(r\"predicted $\\mu_\\phi$\")\n", "plt.title(\"UQL recovers the unmasking quality\")\n", "plt.legend(fontsize=8); plt.tight_layout(); plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Insertion quality $\\nu_\\star$\n", "\n", "When the model inserts a mask into the gap between surviving tokens $\\ell-1$ and $\\ell$,\n", "its **insertion quality** is the probability that the mask decodes to *some* token that\n", "genuinely belongs in that gap, $\\mathcal{S}_\\ell=\\{\\boldsymbol{x}_1^i: s_t[\\ell-1] empty gap\n", "print(f\" insert into an EMPTY gap (nothing belongs): nu* = {nu_empty:.3f} gap={gap_empty}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3.1 Training the insertion-quality predictor $\\nu_\\phi$ (IQL)\n", "\n", "Similarly, $\\nu_\\phi$ is trained with the **Insertion Quality Loss**, which is a BCE against the (soft) target $\\nu_\\star$, taking only the post-insertion sequence $\\boldsymbol{y}$ as input:\n", "\n", "$$\\mathcal{L}_{\\text{IQL}}(\\phi)=\\mathbb{E}\\Big[\\textstyle\\sum_{i\\in\\mathcal{I}}\\text{BCE}\\big(\\nu_\\star^i(\\boldsymbol{y}),\\,\\nu_\\phi^i(\\boldsymbol{y})\\big)\\Big],$$\n", "\n", "whose unique minimizer is $\\nu_\\star$. The predictor learns to assign near-zero quality to inserts whose neighbours are already adjacent in the target." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " step 500 IQL running avg = 0.4728 (irreducible floor = 0.2009)\n", " step 1000 IQL running avg = 0.4763 (irreducible floor = 0.2009)\n", " step 1500 IQL running avg = 0.4646 (irreducible floor = 0.2009)\n", " step 2000 IQL running avg = 0.4717 (irreducible floor = 0.2009)\n", "\n", "running loss 0.4717 sits at the floor 0.2009 -> converged\n", "corr(nu_phi, nu_star) = 0.644\n" ] }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def make_insert_example():\n", " n = np.random.randint(6, 11)\n", " x1 = sample_seq(n)\n", " i = np.random.randint(1, n - 1)\n", " gapsize = int(np.random.choice([0, 0, 1, 2])) # often empty -> nu* = 0\n", " left = x1[i - 1]\n", " rj = i + gapsize\n", " right = x1[rj] if rj < n else PAD\n", " gap = [x1[j] for j in range(i, rj)]\n", " y = [left, MASK, right]\n", " p = posterior_at(y, 1)\n", " nu = float(sum(p[v] for v in set(gap)))\n", " return window_feat(y, 1), torch.tensor([nu]), nu\n", "\n", "# IQL's target nu_star is a *soft* value in [0,1], so BCE(nu_star, nu_phi) bottoms out at E[H(nu_star)] rather than 0\n", "# same idea as UQL, again reported with the floor + EMA\n", "\n", "_, _, nu_pool = zip(*[make_insert_example() for _ in range(4000)])\n", "iql_floor = binary_entropy(nu_pool)\n", "\n", "nu_phi = QualityHead(din)\n", "opt = torch.optim.Adam(nu_phi.parameters(), lr=2e-3)\n", "run = None\n", "for step in range(2000):\n", " feats, soft, _ = zip(*[make_insert_example() for _ in range(64)])\n", " loss = F.binary_cross_entropy(nu_phi(torch.stack(feats)), torch.stack(soft))\n", " opt.zero_grad(); loss.backward(); opt.step()\n", " run = loss.item() if run is None else 0.98 * run + 0.02 * loss.item()\n", " if (step + 1) % 500 == 0:\n", " print(f\" step {step+1:4d} IQL running avg = {run:.4f}\")\n", "\n", "with torch.no_grad():\n", " fs, _, qs = zip(*[make_insert_example() for _ in range(800)])\n", " pred = nu_phi(torch.stack(fs)).squeeze(-1).numpy()\n", "qs = np.array(qs)\n", "print(f\"corr(nu_phi, nu_star) = {np.corrcoef(pred, qs)[0,1]:.3f}\")\n", "\n", "plt.figure(figsize=(4.2, 4.2))\n", "plt.scatter(qs, pred, s=6, alpha=0.25)\n", "bins = np.linspace(0, qs.max() + 1e-6, 9)\n", "idx = np.digitize(qs, bins) - 1\n", "bx = [qs[idx == b].mean() for b in range(len(bins)) if (idx == b).any()]\n", "by = [pred[idx == b].mean() for b in range(len(bins)) if (idx == b).any()]\n", "plt.plot(bx, by, \"o-\", color=\"crimson\", label=\"binned mean\")\n", "lim = max(qs.max(), pred.max())\n", "plt.plot([0, lim], [0, lim], \"k--\", lw=1, label=\"ideal\")\n", "plt.xlabel(r\"true insertion quality $\\nu_\\star$\")\n", "plt.ylabel(r\"predicted $\\nu_\\phi$\")\n", "plt.title(\"IQL recovers the insertion quality\")\n", "plt.legend(fontsize=8); plt.tight_layout(); plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. Quality-guided inference with A2D2\n", "\n", "The A2D2 sampler (`_diffusion_loop`) alternates *unmask* and *insert* Euler steps, and after each one calls the two schedule-aware routines we vendored in §0 to **re-mask low-quality tokens** and **drop low-quality insertions**, keeping the masked/clean counts on the interpolant schedule. We exercise the actual functions with a minimal toy model.\n", "\n", "The toy example only needs `model.planner(seq, t)` returning per-position confidences, and `model.interpolant.{unmask,insertion}_schedule.at(t)` (linear schedule here)." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "class LinearSchedule:\n", " def at(self, t):\n", " return t.clone() if torch.is_tensor(t) else torch.tensor(float(t))\n", "\n", "class ToyInterpolant:\n", " unmask_schedule = LinearSchedule()\n", " insertion_schedule = LinearSchedule()\n", "\n", "class ToyPlanner:\n", " \"\"\"Stand-in for the trained planner. We pass confidences in directly so we can script\n", " exactly which token / insertion is low-quality; in A2D2 these come from mu_phi / nu_phi.\"\"\"\n", " def __init__(self, remask_conf=None, insert_conf=None):\n", " self.remask_conf, self.insert_conf = remask_conf, insert_conf\n", " def __call__(self, seq, t):\n", " B, L = seq.shape\n", " out = {}\n", " if self.remask_conf is not None:\n", " out[\"remasking_conf\"] = self.remask_conf.view(B, L, 1)\n", " if self.insert_conf is not None:\n", " out[\"insertion_conf\"] = self.insert_conf.view(B, L, 1)\n", " return out\n", "\n", "class ToyModel:\n", " def __init__(self, planner):\n", " self.planner = planner\n", " self.interpolant = ToyInterpolant()\n", "\n", "neg_inf = torch.tensor(-np.inf)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4.1 Schedule-aware **re-masking** (low unmasking quality → re-masked)\n", "\n", "Four clean tokens `ABCD` and two masks. Position 1 (`B`) is given a low unmasking-quality confidence (0.10) while the rest are confident. With the schedule asking for one more mask at this step, the routine re-masks exactly the lowest-quality token." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "before: ABCD__\n", "after : A_CD__ <- the low-quality 'B' was re-masked\n" ] } ], "source": [ "new_xt = torch.tensor([[0, 1, 2, 3, MASK, MASK]]) # ABCD__\n", "conf = torch.tensor([[0.9, 0.1, 0.95, 0.92, 0.0, 0.0]]) # pos 1 = low quality\n", "clean_index = (new_xt != MASK) & (new_xt != PAD)\n", "model = ToyModel(ToyPlanner()) # remasking_conf is passed in directly\n", "t, dt = torch.tensor([0.4]), 0.1\n", "\n", "out = apply_schedule_aware_remasking(model, new_xt.clone(), t, dt, conf, clean_index,\n", " MASK, neg_inf, batch_size=1)\n", "print(\"before:\", decode(new_xt[0].tolist()))\n", "print(\"after :\", decode(out[0].tolist()), \" <- the low-quality 'B' was re-masked\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4.2 Schedule-aware **insertion deletion** (low insertion quality → dropped)\n", "\n", "State `A_BC_` after inserting two masks (between `A` & `B`, and after `C`). The first inserted mask gets a low insertion-quality confidence (0.05); with `quality_threshold=0.5` the routine drops it and compacts the sequence, keeping the confident insertion." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "before: A_BC_.\n", "after : ABC_.. <- low-quality insertion dropped, kept the good one\n" ] } ], "source": [ "new_xt = torch.tensor([[0, 1, 2, PAD, PAD, PAD]]) # ABC (3 clean)\n", "xt_tmp = torch.tensor([[0, MASK, 1, 2, MASK, PAD]]) # A_BC_ after inserts\n", "ext = torch.tensor([[0, 1, 0, 1, 0, 0]]) # 1 insert in gaps 1 and 3\n", "orig_mask = torch.tensor([[True, False, True, True, False, False]])\n", "new_pos_orig = torch.tensor([[0, 2, 3, 3, 4, 5]]) # originals shifted right\n", "insert_conf = torch.tensor([[0.9, 0.05, 0.9, 0.9, 0.95, 0.0]]) # inserted mask @pos1 = low\n", "model = ToyModel(ToyPlanner(insert_conf=insert_conf))\n", "t, dt = torch.tensor([0.0]), 0.05\n", "\n", "out = apply_schedule_aware_insertion(model, xt_tmp.clone(), new_xt, t, dt, ext,\n", " MASK, PAD, max_length=6, orig_mask=orig_mask,\n", " new_pos_orig=new_pos_orig, quality_threshold=0.5)\n", "\n", "print(\"before:\", decode(xt_tmp[0].tolist()))\n", "print(\"after :\", decode(out[0].tolist()), \" <- low-quality insertion dropped, kept the good one\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. Putting it together: quality inference catches decoding errors\n", "\n", "The point of both predictors is to flag mistakes *without* access to $\\boldsymbol{x}_1$. Here we corrupt one position of a clean target (decode it to the wrong letter) and let the trained $\\mu_\\phi$ score every clean token. The corrupted position gets the **lowest** predicted unmasking quality — so A2D2's schedule-aware re-masking would target it for a re-do, exactly as intended." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "target x1: BCDECDEAB\n", "decoded y: BCDEEDEAB (position 4 corrupted: C -> E)\n", "\n", " predicted unmasking quality mu_phi per position:\n", " pos 0 (B): 0.666\n", " pos 1 (C): 0.948\n", " pos 2 (D): 0.920\n", " pos 3 (E): 0.339\n", " pos 4 (E): 0.041 *corrupted* <-- lowest, would be re-masked\n", " pos 5 (D): 0.595\n", " pos 6 (E): 0.918\n", " pos 7 (A): 0.957\n", " pos 8 (B): 0.745\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAk4AAAD5CAYAAADRCboRAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAMq9JREFUeJzt3XlcVGX/P/7XwMAMDIssAkqsaoohYOCG4pqoqHd2p9ltBSpW3OCK9jHjdslMUssPZoKVIi1kpLeWCy6oSZr0SU2tlBZXSEEUVJAUHbi+f/ib+TnMIEdZZoDX8/E4f8w11znnfZ1t3nOdTSaEECAiIiKiWpkZOwAiIiKipoKJExEREZFETJyIiIiIJGLiRERERCQREyciIiIiiZg4EREREUnExImIiIhIIiZORERERBIxcSIiIiKSiIlTM7FgwQLIZDJcvXrV4Pf+/v7o379/4wbVAGprp8b48ePh7e3dOEGZkLS0NMhkMpw/f15bZmhZLF68GF9//XW9z//YsWPo168f7O3tIZPJkJSUhP3790Mmk2H//v31Pr/6kJycjLS0NL1yTdwbN25s/KCagVOnTmHBggU622J90RwHavPFF18gKSmpTvOSyWSYPHlynaZRn+7evYtOnTrhnXfeaZT59e/fX+e3448//oClpSV++umnRpm/KWLiRM3S3LlzsXnzZmOHYRIMLYuGSpwmTpyIgoICfPnll8jJycHzzz9f7/OobzUlTlQ3p06dwptvvtkgiZNU9ZE4mZrk5GRcu3YNU6ZMMcr8H3/8cbzwwguYMWOGUeZvCuTGDoCoIbRr187YIZiMxlwWv/76K15++WUMGzZMW/bbb7812vxJnxACt2/fhpWVld53t27dglKplNR7Q8anVquxbNkyTJw4ESqV6oF1//77b1hbWzdIHJMnT0ZISAgOHTqE0NDQBpmHKWOPUwulOQ2xfv16JCQkoG3btrCzs8NTTz2F33//Xadu//794e/vj5ycHISGhsLKygre3t5Yt24dAGD79u148sknYW1tjS5dumDnzp06458+fRoTJkxAhw4dYG1tDXd3d4wcORK//PKLTr2qqiosWrQIHTt2hJWVFVq1aoWAgACsWLHigW357bff4Ovrix49eqCoqAiA4dNTmi73zz77DH5+frC2tkZgYCC2bdumN81vvvkGAQEBUCgU8PX1xYoV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8vICABQUFOg80+nDDz+EWq1GXFwc4uLitOVRUVFIS0tr7PCJiIioBTCZxAkAYmNjERsba/C76snQ/v37Gz4gIiIiovuYxDVORERERE0BEyciIiIiiZg4EREREUnExImIiIhIIiZORERERBIxcSIiIiKSiIkTERERkURMnIiIiIgkYuJEREREJBETJyIiIiKJmDgRERERScTEiYiIiEgiJk5EREREEjFxIiIiIpKIiRMRERGRREyciIiIiCRi4kREREQkERMnIiIiIomYOBERERFJxMSJiIiISCImTkREREQSMXEiIiIikkhu7ACIiB7GmdZhxg5BknZXDhg7BCJqAOxxIiIiIpKIiRMRERGRREyciIiIiCQyqcQpOTkZPj4+UCqVCA4OxoEDD75GIDs7G8HBwVAqlfD19cXq1asbKVIiIiJqiUwmccrIyMD06dORkJCAY8eOISwsDMOGDUNeXp7B+ufOnUNERATCwsJw7NgxvPHGG5g6dSr++9//NnLkRERE1FKYzF11y5cvR3R0NCZNmgQASEpKwq5du5CSkoLExES9+qtXr4anpyeSkpIAAH5+fjhy5AjeffddPPvsswbnUVFRgYqKCu3nGzduAABKS0vruTX3qG//3SDTbQgPswyaSruaY5sA6e1qjm0CgLIqdQNGUn+4/TW/NgFNp13NsU1Aw/1ea6YrhKi9sjABFRUVwtzcXGzatEmnfOrUqaJv374GxwkLCxNTp07VKdu0aZOQy+Xizp07BseZP3++AMCBAwcOHDhw4KA35Ofn15qzmESP09WrV1FZWQlXV1edcldXVxQWFhocp7Cw0GB9tVqNq1evok2bNnrjzJkzB/Hx8drPVVVVKCkpgZOTE2QyWT20pOGVlpbCw8MD+fn5sLOzM3Y49YJtajqaY7vYpqajObaLbTINQgiUlZWhbdu2tdY1icRJo3ryIoR4YEJjqL6hcg2FQgGFQqFT1qpVq0eI1Pjs7OyazAYpFdvUdDTHdrFNTUdzbBfbZHz29vaS6pnExeHOzs4wNzfX610qKirS61XScHNzM1hfLpfDycmpwWIlIiKilsskEidLS0sEBwcjKytLpzwrKwuhoaEGx+nVq5de/d27dyMkJAQWFhYNFisRERG1XCaROAFAfHw81qxZg9TUVOTm5mLGjBnIy8tDTEwMgHvXJ0VGRmrrx8TE4MKFC4iPj0dubi5SU1Oxdu1azJo1y1hNaBQKhQLz58/XO+XYlLFNTUdzbBfb1HQ0x3axTU2PTAgp9941juTkZCxduhQFBQXw9/fH//7v/6Jv374AgPHjx+P8+fPYv3+/tn52djZmzJiBkydPom3btpg9e7Y20SIiIiKqbyaVOBERERGZMpM5VUdERERk6pg4EREREUnExImIiIhIIiZORERERBIxcWoCxo8fD5lMph2cnJwwdOhQ/Pzzz8YOrc4KCwsxZcoU+Pr6QqFQwMPDAyNHjsTevXuNHdpDu389WVhYwNXVFYMHD0ZqaiqqqqqMHV6dVN8GNcPQoUONHdoja25t4vbX9Bw6dAjm5uZNvh0azfm36n5MnJqIoUOHoqCgAAUFBdi7dy/kcjlGjBhh7LDq5Pz58wgODsa+ffuwdOlS/PLLL9i5cycGDBiAuLg4Y4f3SDTr6fz589ixYwcGDBiAadOmYcSIEVCr1cYOr07u3wY1w/r1640dVp00tzZx+2taUlNTMWXKFBw8eBB5eXnGDqdeNMffqupM6l11VDOFQgE3NzcA9143M3v2bPTt2xdXrlxB69atjRzdo4mNjYVMJsOPP/4IlUqlLX/iiScwceJEI0b26O5fT+7u7njyySfRs2dPDBo0CGlpaZg0aZKRI3x097etuWhubeL213SUl5fjq6++wuHDh1FYWIi0tDTMmzfP2GHVWXP8raqOPU5N0M2bN5Geno727ds32ffylZSUYOfOnYiLi9NJmjSa6suXDRk4cCACAwOxadMmY4dCLRC3P9OUkZGBjh07omPHjnjxxRexbt06NLfHKjaH3ypDmDg1Edu2bYONjQ1sbGxga2uLLVu2ICMjA2ZmTXMVnj59GkIIdOrUydihNIpOnTrh/Pnzxg6jTu7fBjXDW2+9Zeyw6qQ5tskQbn+mZ+3atXjxxRcB3Du9dfPmzSZ5bWd1ze23yhCeqmsiBgwYgJSUFAD3emuSk5MxbNgw/Pjjj/Dy8jJydA9P889KJpMZOZLGIYRo8m29fxvUcHR0NFI09aM5tskQbn+m5ffff8ePP/6o7QWUy+UYO3YsUlNT8dRTTxk5urppbr9VhjBxaiJUKhXat2+v/RwcHAx7e3t8/PHHWLRokREjezQdOnSATCZDbm4uRo0aZexwGlxubi58fHyMHUadVN8Gm4Pm2CZDuP2ZlrVr10KtVsPd3V1bJoSAhYUFrl27BgcHByNGVzfN7bfKkObTd9bCyGQymJmZ4datW8YO5ZE4OjpiyJAhWLVqFcrLy/W+v379euMH1UD27duHX375Bc8++6yxQ6EWiNufaVGr1fj000/x3nvv4fjx49rhxIkT8PLyQnp6urFDrFdN/bfKEPY4NREVFRUoLCwEAFy7dg0ffPABbt68iZEjRxo5skeXnJyM0NBQdO/eHQsXLkRAQADUajWysrKQkpKC3NxcY4f40DTrqbKyEpcvX8bOnTuRmJiIESNGIDIy0tjh1cn926CGXC6Hs7OzkSKqu+bWJm5/pm/btm24du0aoqOjYW9vr/Pd6NGjsXbtWkyePNlI0dVdc/yt0iPI5EVFRQkA2sHW1lZ069ZNbNy40dih1dmlS5dEXFyc8PLyEpaWlsLd3V384x//EN9++62xQ3to968nuVwuWrduLZ566imRmpoqKisrjR1enVTfBjVDx44djR3aI2tubeL21zSMGDFCREREGPzu6NGjAoA4evRoI0dVP5rzb9X9ZEI0s/sfiYiIiBoIr3EiIiIikoiJExEREZFETJyIiIiIJGLiRERERCQREyciIiIiiZg4EREREUnExImIiIhIIiZORERERBIxcSIiIiKSiIkTERERkURMnIiIiIgk+n9hN13plaDdRwAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "x1 = sample_seq(9)\n", "y = x1.copy()\n", "bad_pos = 4\n", "y[bad_pos] = (x1[bad_pos] + 2) % V # decode this position to a WRONG letter\n", "\n", "with torch.no_grad():\n", " scores = []\n", " for ell in range(len(y)):\n", " scores.append(mu_phi(window_feat(y, ell).unsqueeze(0)).item())\n", "\n", "print(\"target x1:\", decode(x1))\n", "print(\"decoded y:\", decode(y), f\" (position {bad_pos} corrupted: {LETTERS[x1[bad_pos]]} -> {LETTERS[y[bad_pos]]})\")\n", "print(\"\\n predicted unmasking quality mu_phi per position:\")\n", "for ell, s in enumerate(scores):\n", " flag = \" <-- lowest, would be re-masked\" if ell == int(np.argmin(scores)) else \"\"\n", " star = \" *corrupted*\" if ell == bad_pos else \"\"\n", " print(f\" pos {ell} ({LETTERS[y[ell]]}): {s:.3f}{star}{flag}\")\n", "\n", "plt.figure(figsize=(6, 2.6))\n", "colors = [\"crimson\" if ell == bad_pos else \"steelblue\" for ell in range(len(y))]\n", "plt.bar(range(len(y)), scores, color=colors)\n", "plt.xticks(range(len(y)), [LETTERS[t] for t in y])\n", "plt.ylabel(r\"$\\mu_\\phi$\"); plt.title(\"Unmasking quality flags the corrupted token (red)\")\n", "plt.tight_layout(); plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Summary\n", "\n", "- **Unmasking quality** $\\mu_\\star$ and **insertion quality** $\\nu_\\star$ are defined in closed form here from a known posterior; the predictors $\\mu_\\phi,\\nu_\\phi$ trained with the paper's **UQL / IQL** BCE losses recover them.\n", "- At inference, A2D2 turns these scores that are used in `apply_schedule_aware_remasking` (re-mask low-quality tokens) and `apply_schedule_aware_insertion` (drop low-quality insertions), both shown here on toy states and tied back to a corrupted-decode example.\n", "- Swap the toy `posterior_at` / `ToyPlanner` for a trained any-length MDM + its planner heads (`model/model_wrapper py::RemaskingAnyOrder`) and this becomes the quality-guided decode used in `a2d2_mol` / `a2d2_pep` / `a2d2_language`." ] } ], "metadata": { "kernelspec": { "display_name": "peptune", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.14" } }, "nbformat": 4, "nbformat_minor": 5 }