Alpha: System-One-style typed decision model
Browse files- .gitattributes +1 -0
- README.md +57 -60
- alpha_config.json +10 -0
- alpha_report.png +3 -0
- alpha_s1.py +239 -0
- alpha_train.py +645 -0
- pytorch_model.bin +3 -0
- results.json +435 -0
- tokenizer.json +0 -0
- tokenizer_config.json +17 -0
- training_log.json +1 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
alpha_report.png filter=lfs diff=lfs merge=lfs -text
|
README.md
CHANGED
|
@@ -1,65 +1,62 @@
|
|
| 1 |
---
|
| 2 |
license: apache-2.0
|
| 3 |
-
base_model:
|
| 4 |
-
tags:
|
| 5 |
-
- system-one
|
| 6 |
-
- calibrated-decisions
|
| 7 |
-
- rlcd
|
| 8 |
-
- jev-alternative
|
| 9 |
-
- laya
|
| 10 |
-
- routing
|
| 11 |
-
- guardrails
|
| 12 |
---
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
|
| 29 |
-
|
|
| 30 |
-
|
|
| 31 |
-
|
|
| 32 |
-
|
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
```python
|
| 37 |
-
from
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
res = agent.system_one(
|
| 44 |
-
"Your package was delivered to the front porch.",
|
| 45 |
-
{"delivered": {"type": "noul", "instructions": "Was the delivery completed?"}}
|
| 46 |
-
)
|
| 47 |
-
print(res["answers"]["delivered"])
|
| 48 |
-
|
| 49 |
-
# 2. Multi-Class Choice
|
| 50 |
-
res = agent.system_one(
|
| 51 |
-
"I received a bill with unauthorized roaming charges.",
|
| 52 |
-
{"intent": {
|
| 53 |
-
"type": "choice",
|
| 54 |
-
"instructions": "Identify the customer support ticket intent.",
|
| 55 |
-
"criteria": ["billing_dispute", "technical_issue", "account_closure"]
|
| 56 |
-
}}
|
| 57 |
-
)
|
| 58 |
-
print(res["answers"]["intent"])
|
| 59 |
```
|
| 60 |
-
|
| 61 |
-
## Architecture
|
| 62 |
-
- **Text Backbone:** Bidirectional ModernBERT encoder (423M parameters).
|
| 63 |
-
- **Vision Pathway:** Frozen SigLIP vision tower (`google/siglip-base-patch16-224`) with patch projection.
|
| 64 |
-
- **Adaptive Head Budget:** Dynamic expansion (10k + 48 tokens, capped at 1024) preventing label truncation.
|
| 65 |
-
- **License:** Apache-2.0.
|
|
|
|
| 1 |
---
|
| 2 |
license: apache-2.0
|
| 3 |
+
base_model: distilroberta-base
|
| 4 |
+
tags: [system-one, structured-output, calibrated, classification, parallel-decoding]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
---
|
| 6 |
+
# Alpha (System-One-style typed decision model)
|
| 7 |
+
|
| 8 |
+
Alpha takes unstructured / structured state plus **typed questions with declared options** and returns calibrated probabilities for
|
| 9 |
+
**all questions in one parallel forward pass**. It cannot generate strings and cannot answer outside the declared options
|
| 10 |
+
(masked softmax -> schema violations are impossible by construction). Option embeddings are independent of the state, so a schema can be
|
| 11 |
+
compiled once and cached; cardinality is limited only by memory.
|
| 12 |
+
|
| 13 |
+
Architecture: `distilroberta-base` encoder (state + question slots with `<mask>` readout tokens) -> 2-layer **Slot Reasoner** (set transformer, squared-ReLU,
|
| 14 |
+
zero-init residuals) -> biaffine/cosine scorer against option embeddings with per-question learned temperature + post-hoc temperature (T=1.04).
|
| 15 |
+
|
| 16 |
+
Training: 6000 steps x 32 workflow-style examples (1-4 questions over named fields, mixed from 10 public datasets with paraphrased
|
| 17 |
+
questions/option wordings), proper-scoring-rule loss (NLL + Brier + ordinal term), EMA weights, functional-memory anchor, discovery controller.
|
| 18 |
+
Held-out families (never trained on): cola, dbpedia, offensive.
|
| 19 |
+
|
| 20 |
+
## Results (test splits; see results.json, alpha_report.png)
|
| 21 |
+
| family | acc (seen wording) | acc (unseen wording) | ECE |
|
| 22 |
+
|---|---|---|---|
|
| 23 |
+
| ag_news | 0.926 | 0.924 | 0.032 |
|
| 24 |
+
| banking77 | 0.902 | 0.890 | 0.036 |
|
| 25 |
+
| emotion | 0.922 | 0.894 | 0.030 |
|
| 26 |
+
| imdb | 0.886 | 0.892 | 0.027 |
|
| 27 |
+
| mrpc | 0.822 | 0.822 | 0.042 |
|
| 28 |
+
| news20 | 0.674 | 0.678 | 0.068 |
|
| 29 |
+
| sms | 0.993 | 0.346 | 0.004 |
|
| 30 |
+
| snli | 0.772 | 0.538 | 0.046 |
|
| 31 |
+
| sst2 | 0.912 | 0.910 | 0.034 |
|
| 32 |
+
| yelp | 0.572 | 0.522 | 0.072 |
|
| 33 |
+
|
| 34 |
+
Workflow eval (4 questions per query): per-question acc 0.825, all-correct 0.437, joint-confidence ECE 0.101.
|
| 35 |
+
|
| 36 |
+
Held-out task families (unseen schema wording): zero-shot / after 10 / after 40 gradient steps
|
| 37 |
+
| family | zero-shot | +10 steps | +40 steps |
|
| 38 |
+
|---|---|---|---|
|
| 39 |
+
| cola | 0.374 | 0.658 | 0.686 |
|
| 40 |
+
| dbpedia | 0.312 | 0.586 | 0.952 |
|
| 41 |
+
| offensive | 0.528 | 0.632 | 0.694 |
|
| 42 |
+
|
| 43 |
+
Speed on Tesla T4: p50 11.1 ms, p95 13.5 ms for a 3-question query (local, no network); 354 workflows/s at batch 64.
|
| 44 |
+
Qwen2.5-0.5B-Instruct (generative, same 120 questions): acc 0.583, p50 latency 82 ms vs Alpha acc 0.875, p50 11.1 ms.
|
| 45 |
+
|
| 46 |
+
Framework diagnostics: DMR=1.08; FRR by perturbation: sigma=0.5: FRR 4250.0 sigma=1: FRR 4250.0 sigma=2: FRR 4250.0 sigma=4: FRR 4250.0 sigma=8: FRR 14.2* (* = not re-reached within budget); MGR by checkpoint in results.json.
|
| 47 |
+
|
| 48 |
+
## Honest limits
|
| 49 |
+
* This is a small research model trained on public classification datasets. **It is not a replacement for, and has not been compared against, TypeSafe's Jev**
|
| 50 |
+
(a closed API; its claims were not verified here). Do not read the latency comparison as a Jev comparison.
|
| 51 |
+
* Narrow task coverage (sentiment/topic/intent/NLI/paraphrase/spam/rating); free-form reasoning is out of scope by design.
|
| 52 |
+
* Calibration is measured in-distribution; shift will degrade it.
|
| 53 |
+
|
| 54 |
+
## Usage
|
| 55 |
```python
|
| 56 |
+
from huggingface_hub import snapshot_download; import sys
|
| 57 |
+
p = snapshot_download("SofiTesfay2010/Alpha"); sys.path.insert(0, p)
|
| 58 |
+
from alpha_s1 import Alpha
|
| 59 |
+
m = Alpha.from_pretrained(p, device="cuda").eval()
|
| 60 |
+
print(m.predict({"ticket": "I was charged twice, refund me now."},
|
| 61 |
+
[{"id": "refund", "question": "Does the customer want a refund?", "options": ["no", "yes"]}]))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
alpha_config.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"backbone": "distilroberta-base",
|
| 3 |
+
"d_head": 256,
|
| 4 |
+
"slot_layers": 2,
|
| 5 |
+
"slot_heads": 8,
|
| 6 |
+
"act": "relu2",
|
| 7 |
+
"max_len": 512,
|
| 8 |
+
"field_max": 96,
|
| 9 |
+
"opt_max": 16
|
| 10 |
+
}
|
alpha_report.png
ADDED
|
Git LFS Details
|
alpha_s1.py
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Alpha-S1: a System-One-style model. Unstructured / structured state in, typed probabilistic decisions out.
|
| 3 |
+
|
| 4 |
+
* No text generation. Every question carries its own option list; the model can only score those options
|
| 5 |
+
(masked softmax) -> a type error / out-of-schema answer is impossible by construction.
|
| 6 |
+
* All questions of a query are answered in ONE parallel forward pass (no sequential decoding).
|
| 7 |
+
* Options are embedded independently of the state (bi-encoder side) so a schema can be "compiled" once and cached;
|
| 8 |
+
cardinality is limited only by memory (hundreds of options are cheap).
|
| 9 |
+
* Slot Reasoner: a small set-transformer (squared-ReLU FFN) lets the questions of one query condition on each other.
|
| 10 |
+
* Calibration: per-question learned temperature + post-hoc global temperature; outputs probs, confidence, certainty.
|
| 11 |
+
"""
|
| 12 |
+
import math, json, os
|
| 13 |
+
from dataclasses import dataclass, asdict
|
| 14 |
+
import torch
|
| 15 |
+
import torch.nn as nn
|
| 16 |
+
import torch.nn.functional as F
|
| 17 |
+
from transformers import AutoModel, AutoConfig, AutoTokenizer
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
@dataclass
|
| 21 |
+
class AlphaConfig:
|
| 22 |
+
backbone: str = "distilroberta-base"
|
| 23 |
+
d_head: int = 256
|
| 24 |
+
slot_layers: int = 2
|
| 25 |
+
slot_heads: int = 8
|
| 26 |
+
act: str = "relu2" # "relu2" (squared ReLU, high-accessibility prior) | "gelu"
|
| 27 |
+
max_len: int = 512
|
| 28 |
+
field_max: int = 96
|
| 29 |
+
opt_max: int = 16
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class Tk:
|
| 33 |
+
"""Tokenizer wrapper: no truncation args (thread-safe), caches short strings."""
|
| 34 |
+
def __init__(self, tok): self.tok, self.c = tok, {}
|
| 35 |
+
def __call__(self, text, maxlen=None):
|
| 36 |
+
ids = self.c.get(text)
|
| 37 |
+
if ids is None:
|
| 38 |
+
ids = self.tok(text, add_special_tokens=False)["input_ids"]
|
| 39 |
+
if len(text) < 200: self.c[text] = ids
|
| 40 |
+
return ids[:maxlen] if maxlen else ids
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def opt_batch(texts, tk, tokz, cfg):
|
| 44 |
+
cls, sep, pad = tokz.cls_token_id, tokz.sep_token_id, tokz.pad_token_id
|
| 45 |
+
seqs = [[cls] + tk(" " + t)[:cfg.opt_max] + [sep] for t in texts]
|
| 46 |
+
L = max(len(s) for s in seqs)
|
| 47 |
+
ids = torch.full((len(seqs), L), pad, dtype=torch.long); att = torch.zeros((len(seqs), L), dtype=torch.long)
|
| 48 |
+
for i, s in enumerate(seqs):
|
| 49 |
+
ids[i, :len(s)] = torch.tensor(s); att[i, :len(s)] = 1
|
| 50 |
+
return ids, att
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def build_batch(exs, tk, tokz, cfg):
|
| 54 |
+
"""exs: [{"fields":[(name,text),..], "questions":[{"q":str,"options":[str],"gold":int,"ordinal":bool,"fam":str}]}]"""
|
| 55 |
+
cls, sep, msk, pad = tokz.cls_token_id, tokz.sep_token_id, tokz.mask_token_id, tokz.pad_token_id
|
| 56 |
+
seqs, qposs, rows = [], [], []
|
| 57 |
+
opt_index, opt_texts = {}, []
|
| 58 |
+
for bi, ex in enumerate(exs):
|
| 59 |
+
qids = [tk(" " + q["q"]) for q in ex["questions"]]
|
| 60 |
+
qtot = sum(len(x) + 1 for x in qids) + 3
|
| 61 |
+
nf = max(len(ex["fields"]), 1)
|
| 62 |
+
per = max(8, min(cfg.field_max, (cfg.max_len - qtot) // nf - 8))
|
| 63 |
+
while True:
|
| 64 |
+
ids = [cls]
|
| 65 |
+
for name, text in ex["fields"]:
|
| 66 |
+
ids += tk(f" {name}:") + tk(" " + text, per)
|
| 67 |
+
ids.append(sep)
|
| 68 |
+
pos = []
|
| 69 |
+
for x in qids:
|
| 70 |
+
ids += x; ids.append(msk); pos.append(len(ids) - 1)
|
| 71 |
+
ids.append(sep)
|
| 72 |
+
if len(ids) <= cfg.max_len or per <= 8: break
|
| 73 |
+
per -= 8
|
| 74 |
+
ids = ids[:cfg.max_len]; pos = [min(p, cfg.max_len - 1) for p in pos]
|
| 75 |
+
seqs.append(ids); qposs.append(pos)
|
| 76 |
+
for q in ex["questions"]:
|
| 77 |
+
idxs = []
|
| 78 |
+
for o in q["options"]:
|
| 79 |
+
if o not in opt_index:
|
| 80 |
+
opt_index[o] = len(opt_texts); opt_texts.append(o)
|
| 81 |
+
idxs.append(opt_index[o])
|
| 82 |
+
rows.append((idxs, q.get("gold", 0), bool(q.get("ordinal", False)), q.get("fam", ""), bi))
|
| 83 |
+
B, T = len(seqs), max(len(s) for s in seqs)
|
| 84 |
+
ids = torch.full((B, T), pad, dtype=torch.long); att = torch.zeros((B, T), dtype=torch.long)
|
| 85 |
+
kmax = max(len(p) for p in qposs)
|
| 86 |
+
qpos = torch.zeros((B, kmax), dtype=torch.long); qvalid = torch.zeros((B, kmax), dtype=torch.bool)
|
| 87 |
+
for i, (s, p) in enumerate(zip(seqs, qposs)):
|
| 88 |
+
ids[i, :len(s)] = torch.tensor(s); att[i, :len(s)] = 1
|
| 89 |
+
qpos[i, :len(p)] = torch.tensor(p); qvalid[i, :len(p)] = True
|
| 90 |
+
nQ, nO = len(rows), len(opt_texts)
|
| 91 |
+
allowed = torch.zeros((nQ, nO), dtype=torch.bool); rank = torch.zeros((nQ, nO))
|
| 92 |
+
gold = torch.zeros(nQ, dtype=torch.long); ordn = torch.zeros(nQ, dtype=torch.bool)
|
| 93 |
+
for r, (idxs, g, od, fam, bi) in enumerate(rows):
|
| 94 |
+
allowed[r, idxs] = True
|
| 95 |
+
rank[r, idxs] = torch.arange(len(idxs)).float() / max(len(idxs) - 1, 1)
|
| 96 |
+
gold[r] = idxs[g]; ordn[r] = od
|
| 97 |
+
oi, oa = opt_batch(opt_texts, tk, tokz, cfg)
|
| 98 |
+
return dict(ids=ids, att=att, qpos=qpos, qvalid=qvalid, opt_ids=oi, opt_att=oa, allowed=allowed, rank=rank,
|
| 99 |
+
gold=gold, ordinal=ordn, opt_texts=opt_texts, opt_lists=[r[0] for r in rows],
|
| 100 |
+
gold_pos=[r[1] for r in rows], fams=[r[3] for r in rows], q_ex=[r[4] for r in rows])
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
def to_device(b, dev):
|
| 104 |
+
return {k: (v.to(dev, non_blocking=True) if torch.is_tensor(v) else v) for k, v in b.items()}
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
class EncWrap(nn.Module):
|
| 108 |
+
"""Backbone call with autocast INSIDE forward (required for nn.DataParallel replicas)."""
|
| 109 |
+
def __init__(self, m): super().__init__(); self.m = m
|
| 110 |
+
def forward(self, ids, att):
|
| 111 |
+
with torch.autocast("cuda", dtype=torch.float16, enabled=ids.is_cuda):
|
| 112 |
+
return self.m(input_ids=ids, attention_mask=att).last_hidden_state
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
class SlotLayer(nn.Module):
|
| 116 |
+
"""Pre-LN transformer layer over the query slots of one example; squared-ReLU FFN; zero-init residual branches
|
| 117 |
+
(starts as identity -> the generalizing 'read straight from the encoder' solution is the easiest to reach)."""
|
| 118 |
+
def __init__(self, d, heads, act):
|
| 119 |
+
super().__init__()
|
| 120 |
+
self.n1, self.n2 = nn.LayerNorm(d), nn.LayerNorm(d)
|
| 121 |
+
self.att = nn.MultiheadAttention(d, heads, batch_first=True)
|
| 122 |
+
self.f1, self.f2, self.act = nn.Linear(d, 4 * d), nn.Linear(4 * d, d), act
|
| 123 |
+
nn.init.zeros_(self.att.out_proj.weight); nn.init.zeros_(self.att.out_proj.bias)
|
| 124 |
+
nn.init.zeros_(self.f2.weight); nn.init.zeros_(self.f2.bias)
|
| 125 |
+
def forward(self, x, pad):
|
| 126 |
+
y = self.n1(x)
|
| 127 |
+
a, _ = self.att(y, y, y, key_padding_mask=pad, need_weights=False)
|
| 128 |
+
x = x + a
|
| 129 |
+
h = self.f1(self.n2(x))
|
| 130 |
+
h = F.relu(h) ** 2 if self.act == "relu2" else F.gelu(h)
|
| 131 |
+
return x + self.f2(h)
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
class Alpha(nn.Module):
|
| 135 |
+
def __init__(self, cfg=None, tokenizer=None, pretrained=True, backbone_module=None):
|
| 136 |
+
super().__init__()
|
| 137 |
+
self.cfg = cfg or AlphaConfig()
|
| 138 |
+
self.tokz = tokenizer or AutoTokenizer.from_pretrained(self.cfg.backbone)
|
| 139 |
+
self.tk = Tk(self.tokz)
|
| 140 |
+
if backbone_module is not None: self.backbone = backbone_module
|
| 141 |
+
elif pretrained:
|
| 142 |
+
try: self.backbone = AutoModel.from_pretrained(self.cfg.backbone, add_pooling_layer=False)
|
| 143 |
+
except TypeError: self.backbone = AutoModel.from_pretrained(self.cfg.backbone)
|
| 144 |
+
else:
|
| 145 |
+
c = AutoConfig.from_pretrained(self.cfg.backbone)
|
| 146 |
+
try: self.backbone = AutoModel.from_config(c, add_pooling_layer=False)
|
| 147 |
+
except TypeError: self.backbone = AutoModel.from_config(c)
|
| 148 |
+
d = self.backbone.config.hidden_size
|
| 149 |
+
self.ln = nn.LayerNorm(d)
|
| 150 |
+
self.slots = nn.ModuleList([SlotLayer(d, self.cfg.slot_heads, self.cfg.act) for _ in range(self.cfg.slot_layers)])
|
| 151 |
+
self.q_proj, self.o_proj = nn.Linear(d, self.cfg.d_head), nn.Linear(d, self.cfg.d_head)
|
| 152 |
+
self.temp = nn.Linear(d, 1) # per-question (heteroscedastic) temperature
|
| 153 |
+
nn.init.zeros_(self.temp.weight); nn.init.constant_(self.temp.bias, 0.11)
|
| 154 |
+
self.log_scale = nn.Parameter(torch.tensor(math.log(10.0)))
|
| 155 |
+
self.register_buffer("post_T", torch.tensor(1.0)) # post-hoc global temperature (fit on held-out calibration set)
|
| 156 |
+
object.__setattr__(self, "_enc", EncWrap(self.backbone)) # not registered: shares backbone params
|
| 157 |
+
object.__setattr__(self, "_dp", None)
|
| 158 |
+
self._opt_cache = {}
|
| 159 |
+
|
| 160 |
+
# ---- plumbing ----
|
| 161 |
+
def use_data_parallel(self):
|
| 162 |
+
if torch.cuda.device_count() > 1:
|
| 163 |
+
object.__setattr__(self, "_dp", nn.DataParallel(EncWrap(self.backbone)))
|
| 164 |
+
return self
|
| 165 |
+
|
| 166 |
+
def train(self, mode=True):
|
| 167 |
+
self._opt_cache = {}
|
| 168 |
+
return super().train(mode)
|
| 169 |
+
|
| 170 |
+
def new_params(self):
|
| 171 |
+
bb = {id(p) for p in self.backbone.parameters()}
|
| 172 |
+
return [p for p in self.parameters() if id(p) not in bb]
|
| 173 |
+
|
| 174 |
+
def encode(self, ids, att):
|
| 175 |
+
enc = self._dp if (self._dp is not None and ids.size(0) >= 8) else self._enc
|
| 176 |
+
return enc(ids, att)
|
| 177 |
+
|
| 178 |
+
def embed_options(self, opt_ids, opt_att):
|
| 179 |
+
H = self.encode(opt_ids, opt_att).float(); m = opt_att.unsqueeze(-1).float()
|
| 180 |
+
return (H * m).sum(1) / m.sum(1).clamp(min=1)
|
| 181 |
+
|
| 182 |
+
# ---- core: all questions, all options, one pass ----
|
| 183 |
+
def forward(self, b, opt_emb=None):
|
| 184 |
+
H = self.encode(b["ids"], b["att"])
|
| 185 |
+
B = H.size(0)
|
| 186 |
+
hq = H[torch.arange(B, device=H.device)[:, None], b["qpos"]].float()
|
| 187 |
+
hq = self.ln(hq)
|
| 188 |
+
pad = ~b["qvalid"]
|
| 189 |
+
for layer in self.slots: hq = layer(hq, pad)
|
| 190 |
+
hq = hq[b["qvalid"]] # [nQ, d] row-major == question order in batch
|
| 191 |
+
if opt_emb is None: opt_emb = self.embed_options(b["opt_ids"], b["opt_att"])
|
| 192 |
+
q = F.normalize(self.q_proj(hq).float(), dim=-1); o = F.normalize(self.o_proj(opt_emb).float(), dim=-1)
|
| 193 |
+
T = F.softplus(self.temp(hq).float()) + 0.25
|
| 194 |
+
logits = (q @ o.T) * self.log_scale.exp() / T
|
| 195 |
+
return logits.masked_fill(~b["allowed"], -1e4) # type safety: only declared options exist
|
| 196 |
+
|
| 197 |
+
# ---- public API ----
|
| 198 |
+
@torch.no_grad()
|
| 199 |
+
def predict(self, state, questions):
|
| 200 |
+
"""state: {field: text}; questions: [{"id","question","options":[...],"ordinal":bool}] -> {id: {...}}"""
|
| 201 |
+
dev = next(self.parameters()).device
|
| 202 |
+
if self.training: self.eval() # (train() clears the option cache)
|
| 203 |
+
ex = dict(fields=list(state.items()),
|
| 204 |
+
questions=[dict(q=q["question"], options=list(q["options"]), gold=0, ordinal=q.get("ordinal", False)) for q in questions])
|
| 205 |
+
b = to_device(build_batch([ex], self.tk, self.tokz, self.cfg), dev)
|
| 206 |
+
miss = [t for t in b["opt_texts"] if t not in self._opt_cache]
|
| 207 |
+
if miss: # "schema compilation": option embeddings cached
|
| 208 |
+
oi, oa = opt_batch(miss, self.tk, self.tokz, self.cfg)
|
| 209 |
+
emb = self.embed_options(oi.to(dev), oa.to(dev))
|
| 210 |
+
for t, e in zip(miss, emb): self._opt_cache[t] = e
|
| 211 |
+
opt_emb = torch.stack([self._opt_cache[t] for t in b["opt_texts"]])
|
| 212 |
+
logits = self.forward(b, opt_emb) / self.post_T
|
| 213 |
+
out = {}
|
| 214 |
+
for r, q in enumerate(questions):
|
| 215 |
+
idx = b["opt_lists"][r]
|
| 216 |
+
p = F.softmax(logits[r, idx], -1).cpu()
|
| 217 |
+
K = len(idx); j = int(p.argmax())
|
| 218 |
+
ent = float(-(p * p.clamp_min(1e-9).log()).sum())
|
| 219 |
+
out[q["id"]] = dict(answer=q["options"][j], probs={o: float(x) for o, x in zip(q["options"], p)},
|
| 220 |
+
confidence=float(p[j]), certainty=(1 - ent / math.log(K)) if K > 1 else 1.0)
|
| 221 |
+
return out
|
| 222 |
+
|
| 223 |
+
def save_pretrained(self, path):
|
| 224 |
+
os.makedirs(path, exist_ok=True)
|
| 225 |
+
torch.save({k: v.detach().cpu() for k, v in self.state_dict().items()}, f"{path}/pytorch_model.bin")
|
| 226 |
+
json.dump(asdict(self.cfg), open(f"{path}/alpha_config.json", "w"), indent=1)
|
| 227 |
+
self.tokz.save_pretrained(path)
|
| 228 |
+
|
| 229 |
+
@classmethod
|
| 230 |
+
def from_pretrained(cls, path_or_repo, device=None):
|
| 231 |
+
if not os.path.isdir(path_or_repo):
|
| 232 |
+
from huggingface_hub import snapshot_download
|
| 233 |
+
path_or_repo = snapshot_download(path_or_repo)
|
| 234 |
+
cfg = AlphaConfig(**json.load(open(f"{path_or_repo}/alpha_config.json")))
|
| 235 |
+
m = cls(cfg, AutoTokenizer.from_pretrained(path_or_repo), pretrained=False)
|
| 236 |
+
missing, unexpected = m.load_state_dict(torch.load(f"{path_or_repo}/pytorch_model.bin", map_location="cpu"), strict=False)
|
| 237 |
+
missing = [k for k in missing if "pooler" not in k]
|
| 238 |
+
assert not missing, f"missing keys: {missing[:5]}"
|
| 239 |
+
return m.to(device) if device else m
|
alpha_train.py
ADDED
|
@@ -0,0 +1,645 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Alpha training / benchmark / publish pipeline (Kaggle, 2x T4).
|
| 3 |
+
|
| 4 |
+
Framework rules from the spec are used as *design priors and instruments*, not as proven facts:
|
| 5 |
+
* Accessibility A(theta,F): squared-ReLU + zero-init Slot Reasoner, pretrained encoder, schema-compositional heads
|
| 6 |
+
(the general function is the easiest one to reach), many paraphrased schemas (high information rate).
|
| 7 |
+
* Regularisation shapes the manifold: very different weight decay for pretrained backbone vs new modules, adapted online
|
| 8 |
+
by the Discovery Controller from rho = d(val)/d(train) (proxy for P(B_G)/P(B_M)).
|
| 9 |
+
* Functional memory M_F: function-space signatures of past EMA checkpoints on diagnostic set E_F, used as a KL anchor
|
| 10 |
+
(self-distillation to earlier functions); L_FRR measured mid-training scales the anchor weight.
|
| 11 |
+
* FRR: perturb the discovered solution (basin test), retrain, time re-discovery -> FRR = T_first / T_re.
|
| 12 |
+
* Meta-grokking: held-out task families never trained on; adaptation speed measured at checkpoints (MGR).
|
| 13 |
+
* DMR: T_discover / T_memorize from train/val trajectories ( ~1 => no delayed generalisation, i.e. 'groks from the start').
|
| 14 |
+
"""
|
| 15 |
+
import os, re, json, math, time, random, shutil
|
| 16 |
+
import numpy as np
|
| 17 |
+
import torch
|
| 18 |
+
import torch.nn.functional as F
|
| 19 |
+
from alpha_s1 import Alpha, AlphaConfig, build_batch, to_device
|
| 20 |
+
|
| 21 |
+
dev = "cuda:0" if torch.cuda.is_available() else "cpu"
|
| 22 |
+
ac = lambda: torch.autocast("cuda", dtype=torch.float16, enabled=torch.cuda.is_available())
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
class C:
|
| 26 |
+
backbone = "distilroberta-base" # try "roberta-base" for more accuracy (slower)
|
| 27 |
+
repo_id = "SofiTesfay2010/Alpha"
|
| 28 |
+
seed = 0
|
| 29 |
+
steps, bs = 6000, 32
|
| 30 |
+
lr_bb, lr_new = 5e-5, 5e-4
|
| 31 |
+
wd_bb, wd_new, wd_min, wd_max = 0.01, 0.5, 0.05, 2.0
|
| 32 |
+
warmup, clip = 300, 1.0
|
| 33 |
+
ls, brier_w, ord_w = 0.02, 0.3, 1.0
|
| 34 |
+
ema = 0.999
|
| 35 |
+
eval_every, mem_every, anchor_every, lam_mem = 250, 1000, 4, 0.3
|
| 36 |
+
probe_every, probe_steps, probe_bs, probe_test_n = 1000, 40, 16, 200
|
| 37 |
+
probe_at = (0, 5, 10, 20, 40)
|
| 38 |
+
fast_n = 48
|
| 39 |
+
n_cal, n_test = 150, 500
|
| 40 |
+
sigmas = [0.5, 1, 2, 4, 8]
|
| 41 |
+
noise_unit, frr_max_steps, frr_every = 0.02, 300, 25
|
| 42 |
+
llm_baseline = "Qwen/Qwen2.5-0.5B-Instruct"
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
# ----------------------------------------------------------------------------------------------- data
|
| 46 |
+
def S(paths, fields, fn, qs, names=None, alts=None, tr="train", va="validation", ordinal=False, held=False, ntr=30000, camel=False):
|
| 47 |
+
return dict(paths=paths, fields=fields, fn=fn, qs=qs, names=names, alts=alts, tr=tr, va=va, ordinal=ordinal, held=held, ntr=ntr, camel=camel)
|
| 48 |
+
|
| 49 |
+
SPECS = dict(
|
| 50 |
+
sst2=S([("nyu-mll/glue", "sst2")], ["sentence"], [["review"], ["comment"], ["snippet"]],
|
| 51 |
+
["What is the sentiment of the {f}?", "Is the {f} positive or negative?", "Judge the attitude expressed in the {f}."],
|
| 52 |
+
names=["negative", "positive"], alts=[["negative", "positive"], ["bad", "good"], ["unfavorable", "favorable"]]),
|
| 53 |
+
imdb=S([("stanfordnlp/imdb",)], ["text"], [["movie_review"], ["critique"]],
|
| 54 |
+
["Is the {f} favorable or unfavorable?", "What verdict does the {f} give?", "Does the author of the {f} like the film?"],
|
| 55 |
+
names=["negative", "positive"], alts=[["negative", "positive"], ["thumbs down", "thumbs up"], ["dislikes it", "likes it"]], va="test", ntr=20000),
|
| 56 |
+
ag_news=S([("fancyzhx/ag_news",)], ["text"], [["headline"], ["article"], ["news_item"]],
|
| 57 |
+
["Which section would the {f} appear in?", "What topic is the {f} about?", "Categorize the {f}."],
|
| 58 |
+
names=["world news", "sports", "business", "science and technology"],
|
| 59 |
+
alts=[["world news", "sports", "business", "science and technology"], ["world", "sports", "finance", "tech"], ["international affairs", "athletics", "economy", "technology"]], va="test"),
|
| 60 |
+
emotion=S([("dair-ai/emotion",)], ["text"], [["message"], ["post"], ["tweet"]],
|
| 61 |
+
["Which emotion does the {f} convey?", "What is the author of the {f} feeling?", "Name the dominant emotion in the {f}."],
|
| 62 |
+
names=["sadness", "joy", "love", "anger", "fear", "surprise"],
|
| 63 |
+
alts=[["sadness", "joy", "love", "anger", "fear", "surprise"], ["sad", "happy", "affection", "angry", "afraid", "astonished"], ["grief", "delight", "adoration", "rage", "dread", "shock"]]),
|
| 64 |
+
banking77=S([("PolyAI/banking77",), ("mteb/banking77",)], ["text"], [["customer_message"], ["support_query"]],
|
| 65 |
+
["What is the customer asking about in the {f}?", "Which intent does the {f} express?", "Classify the banking request in the {f}."], va="test"),
|
| 66 |
+
yelp=S([("Yelp/yelp_review_full",)], ["text"], [["review"], ["feedback"]],
|
| 67 |
+
["How many stars does the {f} deserve?", "Rate the {f}.", "What score would the author of the {f} give?"],
|
| 68 |
+
names=["1 star", "2 stars", "3 stars", "4 stars", "5 stars"],
|
| 69 |
+
alts=[["1 star", "2 stars", "3 stars", "4 stars", "5 stars"], ["terrible", "poor", "average", "good", "excellent"], ["very negative", "negative", "neutral", "positive", "very positive"]],
|
| 70 |
+
va="test", ordinal=True),
|
| 71 |
+
snli=S([("stanfordnlp/snli",)], ["premise", "hypothesis"], [["premise", "hypothesis"], ["context", "claim"]],
|
| 72 |
+
["What is the logical relationship between {f}?", "Does the second follow from the first, contradict it, or neither? ({f})", "Relation between {f}:"],
|
| 73 |
+
names=["entailment", "neutral", "contradiction"],
|
| 74 |
+
alts=[["entailment", "neutral", "contradiction"], ["supported", "undetermined", "contradicted"], ["follows", "unrelated", "conflicts"]], ntr=60000),
|
| 75 |
+
sms=S([("ucirvine/sms_spam",)], ["sms"], [["message"], ["text_message"]],
|
| 76 |
+
["Is the {f} spam?", "Classify the {f}.", "Is the {f} an unwanted advertisement or a normal message?"],
|
| 77 |
+
names=["legitimate", "spam"], alts=[["legitimate", "spam"], ["ham", "spam"], ["normal", "unwanted"]], va=None),
|
| 78 |
+
news20=S([("SetFit/20_newsgroups",)], ["text"], [["post"], ["usenet_message"]],
|
| 79 |
+
["Which newsgroup does the {f} belong to?", "What topic does the {f} discuss?", "Categorize the {f} by topic."], va="test"),
|
| 80 |
+
mrpc=S([("nyu-mll/glue", "mrpc")], ["sentence1", "sentence2"], [["sentence_a", "sentence_b"], ["statement_1", "statement_2"]],
|
| 81 |
+
["Do {f} mean the same thing?", "Are {f} paraphrases of each other?", "Compare the meaning of {f}."],
|
| 82 |
+
names=["different meaning", "same meaning"], alts=[["different meaning", "same meaning"], ["not paraphrase", "paraphrase"], ["unrelated", "equivalent"]]),
|
| 83 |
+
# ---- held-out families: NEVER trained on in the main run; used for zero-shot + meta-grokking probes ----
|
| 84 |
+
dbpedia=S([("fancyzhx/dbpedia_14",)], ["content"], [["entry"], ["wiki_summary"]],
|
| 85 |
+
["What kind of entity does the {f} describe?", "Classify the subject of the {f}.", "Which category fits the {f}?"], va="test", held=True, ntr=20000, camel=True),
|
| 86 |
+
offensive=S([("cardiffnlp/tweet_eval", "offensive")], ["text"], [["tweet"], ["post"]],
|
| 87 |
+
["Is the {f} offensive?", "Does the {f} contain abuse or insults?", "Moderate the {f}."],
|
| 88 |
+
names=["not offensive", "offensive"], alts=[["not offensive", "offensive"], ["civil", "abusive"], ["acceptable", "insulting"]], held=True),
|
| 89 |
+
cola=S([("nyu-mll/glue", "cola")], ["sentence"], [["sentence"], ["utterance"]],
|
| 90 |
+
["Is the {f} grammatical?", "Is the {f} well-formed English?", "Judge the grammar of the {f}."],
|
| 91 |
+
names=["ungrammatical", "grammatical"], alts=[["ungrammatical", "grammatical"], ["incorrect", "correct"], ["unacceptable", "acceptable"]], held=True),
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
DATA, ST = {}, {}
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def _clean(n, camel):
|
| 98 |
+
n = n.replace("_", " ").replace(".", " ")
|
| 99 |
+
if camel: n = re.sub(r"(?<!^)(?=[A-Z])", " ", n)
|
| 100 |
+
return n.lower().strip()
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
def load_all():
|
| 104 |
+
from datasets import load_dataset
|
| 105 |
+
for name, sp in SPECS.items():
|
| 106 |
+
for p in sp["paths"]:
|
| 107 |
+
try:
|
| 108 |
+
if sp["va"]:
|
| 109 |
+
dtr = load_dataset(*p, split=sp["tr"]).shuffle(seed=0); dva = load_dataset(*p, split=sp["va"]).shuffle(seed=0)
|
| 110 |
+
else:
|
| 111 |
+
full = load_dataset(*p, split="train").shuffle(seed=0); cut = int(0.9 * len(full))
|
| 112 |
+
dtr, dva = full.select(range(cut)), full.select(range(cut, len(full)))
|
| 113 |
+
dtr = dtr.select(range(min(len(dtr), sp["ntr"]))); dva = dva.select(range(min(len(dva), 1500)))
|
| 114 |
+
names = sp["names"]
|
| 115 |
+
if names is None:
|
| 116 |
+
feat = dtr.features["label"]
|
| 117 |
+
if hasattr(feat, "names"): names = list(feat.names)
|
| 118 |
+
else:
|
| 119 |
+
m = {int(l): t for l, t in zip(dtr["label"], dtr["label_text"])}; names = [m[i] for i in range(max(m) + 1)]
|
| 120 |
+
names = [_clean(n, sp["camel"]) for n in names]
|
| 121 |
+
alts = sp["alts"] or [names]
|
| 122 |
+
|
| 123 |
+
def rows(d):
|
| 124 |
+
cols = [d[f] for f in sp["fields"]]; lab = d["label"]
|
| 125 |
+
return [(tuple(str(c[i])[:1200] for c in cols), int(lab[i])) for i in range(len(lab)) if int(lab[i]) >= 0]
|
| 126 |
+
R = dict(train=rows(dtr), val=rows(dva))
|
| 127 |
+
assert len(R["val"]) >= 60 and len(R["train"]) >= 200
|
| 128 |
+
DATA[name] = dict(spec=sp, names=names, alts=alts, rows=R)
|
| 129 |
+
print(f"[data] {name:10s} classes={len(names):3d} train={len(R['train']):6d} val={len(R['val']):5d} {'(held-out)' if sp['held'] else ''}")
|
| 130 |
+
break
|
| 131 |
+
except Exception as e:
|
| 132 |
+
print(f"[skip] {name} via {p}: {type(e).__name__}: {str(e)[:100]}")
|
| 133 |
+
ST["train_fams"] = sorted(f for f in DATA if not DATA[f]["spec"]["held"])
|
| 134 |
+
ST["held_fams"] = sorted(f for f in DATA if DATA[f]["spec"]["held"])
|
| 135 |
+
assert len(ST["train_fams"]) >= 4, "too few training families loaded (is internet enabled?)"
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def make_example(rng, fams, split="train", wording="train", idx=None, lo=0):
|
| 139 |
+
fields, qs, used = [], [], set()
|
| 140 |
+
for fam in fams:
|
| 141 |
+
D = DATA[fam]; sp = D["spec"]; rows = D["rows"][split]
|
| 142 |
+
if idx is not None: texts, label = rows[idx % len(rows)]
|
| 143 |
+
else: texts, label = rows[rng.randrange(lo if len(rows) > lo else 0, len(rows))]
|
| 144 |
+
nm = []
|
| 145 |
+
for n0 in rng.choice(sp["fn"]):
|
| 146 |
+
n1, c = n0, 2
|
| 147 |
+
while n1 in used: n1 = f"{n0}_{c}"; c += 1
|
| 148 |
+
used.add(n1); nm.append(n1)
|
| 149 |
+
fields += list(zip(nm, texts))
|
| 150 |
+
if wording == "unseen": q, alt = sp["qs"][2], D["alts"][-1]
|
| 151 |
+
elif wording == "any": q, alt = rng.choice(sp["qs"]), rng.choice(D["alts"])
|
| 152 |
+
else: q, alt = rng.choice(sp["qs"][:2]), rng.choice(D["alts"][:-1] or D["alts"])
|
| 153 |
+
qs.append(dict(q=q.format(f=" and ".join(nm)), options=list(alt), gold=label, ordinal=sp["ordinal"], fam=fam))
|
| 154 |
+
rng.shuffle(fields); rng.shuffle(qs)
|
| 155 |
+
return dict(fields=fields, questions=qs)
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
def sample_exs(rng, n):
|
| 159 |
+
fams, w = ST["train_fams"], ST["w"]; out = []
|
| 160 |
+
for _ in range(n):
|
| 161 |
+
k = min(rng.choices([1, 2, 3, 4], [.3, .3, .25, .15])[0], len(fams)); ch = []
|
| 162 |
+
while len(ch) < k:
|
| 163 |
+
f = rng.choices(fams, w)[0]
|
| 164 |
+
if f not in ch: ch.append(f)
|
| 165 |
+
out.append(make_example(rng, ch))
|
| 166 |
+
return out
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
def prep(exs, bs=48):
|
| 170 |
+
m = ST["model"]
|
| 171 |
+
return [to_device(build_batch(exs[i:i + bs], m.tk, m.tokz, m.cfg), dev) for i in range(0, len(exs), bs)]
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
def val_examples(fam, lo, hi, wording):
|
| 175 |
+
n = len(DATA[fam]["rows"]["val"])
|
| 176 |
+
return [make_example(random.Random(1000 + i), [fam], "val", wording, idx=i) for i in range(lo, min(hi, n))]
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
# ----------------------------------------------------------------------------------------------- metrics
|
| 180 |
+
def ece_fn(conf, corr, nb=15):
|
| 181 |
+
conf, corr = np.asarray(conf, float), np.asarray(corr, float); e = 0.0
|
| 182 |
+
edges = np.linspace(0, 1, nb + 1)
|
| 183 |
+
for lo, hi in zip(edges[:-1], edges[1:]):
|
| 184 |
+
m = (conf > lo) & (conf <= hi)
|
| 185 |
+
if m.any(): e += m.mean() * abs(corr[m].mean() - conf[m].mean())
|
| 186 |
+
return float(e)
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
@torch.no_grad()
|
| 190 |
+
def predict_res(model, batches):
|
| 191 |
+
model.eval(); out = []
|
| 192 |
+
for b in batches:
|
| 193 |
+
with ac(): lg = model(b)
|
| 194 |
+
lg = lg.float().cpu()
|
| 195 |
+
for r, idx in enumerate(b["opt_lists"]):
|
| 196 |
+
out.append((b["fams"][r], lg[r, idx].numpy(), b["gold_pos"][r]))
|
| 197 |
+
return out
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
def _calc(items):
|
| 201 |
+
acc = nll = br = 0.0; conf, corr = [], []
|
| 202 |
+
for lg, g in items:
|
| 203 |
+
z = lg - lg.max(); lp = z - np.log(np.exp(z).sum()); p = np.exp(lp)
|
| 204 |
+
oh = np.zeros_like(p); oh[g] = 1
|
| 205 |
+
acc += float(p.argmax() == g); nll += -lp[g]; br += ((p - oh) ** 2).sum()
|
| 206 |
+
conf.append(float(p.max())); corr.append(float(p.argmax() == g))
|
| 207 |
+
n = len(items)
|
| 208 |
+
return dict(acc=acc / n, nll=nll / n, brier=br / n, ece=ece_fn(conf, corr), n=n, conf=conf, corr=corr)
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
def stat(res, T=1.0):
|
| 212 |
+
per = {}
|
| 213 |
+
for fam, lg, g in res: per.setdefault(fam, []).append((lg / T, g))
|
| 214 |
+
P = {f: _calc(v) for f, v in per.items()}
|
| 215 |
+
allitems = [x for v in per.values() for x in v]; micro = _calc(allitems)
|
| 216 |
+
mac = lambda k: float(np.mean([P[f][k] for f in P]))
|
| 217 |
+
return dict(per=P, score=mac("acc"), nll=mac("nll"), brier=mac("brier"), ece=micro["ece"], micro=micro,
|
| 218 |
+
per_acc={f: P[f]["acc"] for f in P})
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def fast_eval(model, which):
|
| 222 |
+
return stat(predict_res(model, ST["fast_" + which]), float(model.post_T))
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
# ----------------------------------------------------------------------------------------------- training parts
|
| 226 |
+
def loss_fn(model, b):
|
| 227 |
+
lg = model(b).float(); lp = F.log_softmax(lg, -1); al = b["allowed"]
|
| 228 |
+
ar = torch.arange(lg.size(0), device=lg.device)
|
| 229 |
+
nll = -lp[ar, b["gold"]]
|
| 230 |
+
uni = -(lp.masked_fill(~al, 0.0)).sum(1) / al.sum(1)
|
| 231 |
+
p = lp.exp(); oh = F.one_hot(b["gold"], lg.size(1)).float()
|
| 232 |
+
brier = ((p - oh) ** 2).sum(1)
|
| 233 |
+
rg = b["rank"][ar, b["gold"]]
|
| 234 |
+
ordl = (p * (b["rank"] - rg[:, None]) ** 2 * al).sum(1)
|
| 235 |
+
L = (1 - C.ls) * nll + C.ls * uni + C.brier_w * brier + C.ord_w * b["ordinal"].float() * ordl
|
| 236 |
+
return L.mean(), float(nll.mean())
|
| 237 |
+
|
| 238 |
+
|
| 239 |
+
def make_scaler():
|
| 240 |
+
try: return torch.amp.GradScaler("cuda", enabled=torch.cuda.is_available())
|
| 241 |
+
except Exception: return torch.cuda.amp.GradScaler(enabled=torch.cuda.is_available())
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
def make_opt(model, lr_bb, lr_new, wd_new):
|
| 245 |
+
def split(ps): return [p for p in ps if p.ndim >= 2], [p for p in ps if p.ndim < 2]
|
| 246 |
+
bd, bn = split(list(model.backbone.parameters())); nd, nn_ = split(model.new_params())
|
| 247 |
+
gs = [dict(params=bd, base_lr=lr_bb, lr=lr_bb, weight_decay=C.wd_bb, tag="bb"), dict(params=bn, base_lr=lr_bb, lr=lr_bb, weight_decay=0.0, tag="bb0"),
|
| 248 |
+
dict(params=nd, base_lr=lr_new, lr=lr_new, weight_decay=wd_new, tag="new"), dict(params=nn_, base_lr=lr_new, lr=lr_new, weight_decay=0.0, tag="new0")]
|
| 249 |
+
return torch.optim.AdamW([g for g in gs if g["params"]], betas=(0.9, 0.98), eps=1e-6)
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
def sgd_step(model, opt, scaler, b, mem=None, lam=0.0, anchor=False):
|
| 253 |
+
model.train()
|
| 254 |
+
with ac():
|
| 255 |
+
loss, nll = loss_fn(model, b)
|
| 256 |
+
if anchor and mem is not None and mem.entries: loss = loss + lam * mem.anchor(model)
|
| 257 |
+
opt.zero_grad(set_to_none=True); scaler.scale(loss).backward(); scaler.unscale_(opt)
|
| 258 |
+
gn = torch.nn.utils.clip_grad_norm_(model.parameters(), C.clip); scaler.step(opt); scaler.update()
|
| 259 |
+
return nll, float(gn)
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
def clone_state(m): return {k: v.detach().cpu().clone() for k, v in m.state_dict().items()}
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
class EMA:
|
| 266 |
+
def __init__(s, model, decay):
|
| 267 |
+
s.d, s.bk = decay, None
|
| 268 |
+
s.sh = {k: v.detach().clone().float() for k, v in model.state_dict().items() if v.dtype.is_floating_point}
|
| 269 |
+
@torch.no_grad()
|
| 270 |
+
def update(s, model, step):
|
| 271 |
+
d = min(s.d, (1 + step) / (10 + step))
|
| 272 |
+
for k, v in model.state_dict().items():
|
| 273 |
+
if k in s.sh: s.sh[k].mul_(d).add_(v.detach().float(), alpha=1 - d)
|
| 274 |
+
@torch.no_grad()
|
| 275 |
+
def apply(s, model):
|
| 276 |
+
sd = model.state_dict(); s.bk = {k: sd[k].detach().clone() for k in s.sh}
|
| 277 |
+
model.load_state_dict({k: s.sh[k].to(sd[k].dtype) for k in s.sh}, strict=False)
|
| 278 |
+
@torch.no_grad()
|
| 279 |
+
def restore(s, model): model.load_state_dict(s.bk, strict=False)
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
class FMem:
|
| 283 |
+
"""Functional memory M_F: entries = {step, signature Sigma_F (dense logits on diagnostic set E_F), val score}."""
|
| 284 |
+
def __init__(s, diag_batch): s.b, s.entries = diag_batch, []
|
| 285 |
+
@torch.no_grad()
|
| 286 |
+
def add(s, model, step, score):
|
| 287 |
+
model.eval()
|
| 288 |
+
with ac(): lg = model(s.b).float()
|
| 289 |
+
s.entries.append(dict(step=step, sig=lg.cpu().half(), score=score))
|
| 290 |
+
def anchor(s, model):
|
| 291 |
+
e = random.choice(s.entries); old = e["sig"].to(s.b["allowed"].device).float()
|
| 292 |
+
lp = F.log_softmax(model(s.b).float(), -1); p = F.softmax(old, -1); lpo = F.log_softmax(old, -1)
|
| 293 |
+
return ((p * (lpo - lp)).masked_fill(~s.b["allowed"], 0.0)).sum(1).mean()
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
class Controller:
|
| 297 |
+
"""Discovery controller: rho = d(val nll)/d(train nll) ~ share of fitting progress that generalises (proxy of P(B_G)/P(B_M))."""
|
| 298 |
+
def __init__(s): s.wd, s.rho, s.prev, s.LFRR = C.wd_new, None, None, 0.0
|
| 299 |
+
def update(s, rec):
|
| 300 |
+
if s.prev is not None:
|
| 301 |
+
dtr, dv = s.prev["tr_nll"] - rec["tr_nll"], s.prev["nll"] - rec["nll"]
|
| 302 |
+
if dtr > 1e-3:
|
| 303 |
+
r = float(np.clip(dv / dtr, -1, 2)); s.rho = r if s.rho is None else 0.5 * s.rho + 0.5 * r
|
| 304 |
+
if s.rho is not None:
|
| 305 |
+
if s.rho < 0.3: s.wd = min(C.wd_max, s.wd * 1.25) # memorising -> shape manifold harder
|
| 306 |
+
elif s.rho > 0.8: s.wd = max(C.wd_min, s.wd * 0.9) # generalising -> relax
|
| 307 |
+
s.prev = rec
|
| 308 |
+
|
| 309 |
+
|
| 310 |
+
def perturb(model, sigma):
|
| 311 |
+
with torch.no_grad():
|
| 312 |
+
for p in model.parameters():
|
| 313 |
+
if p.ndim >= 2: p.add_(torch.randn_like(p) * p.std() * sigma * C.noise_unit)
|
| 314 |
+
|
| 315 |
+
|
| 316 |
+
def frr_test(model, hist, final_score, sigmas):
|
| 317 |
+
"""FRR = T_first / T_re. T_first: first logged step the main run reached tau. T_re: steps to re-reach tau after perturbing."""
|
| 318 |
+
snap = clone_state(model); tau = final_score - 0.01
|
| 319 |
+
T_first = next((h["step"] for h in hist if h["score"] >= tau), hist[-1]["step"]); res = {}
|
| 320 |
+
for sg in sigmas:
|
| 321 |
+
model.load_state_dict(snap); torch.manual_seed(int(sg * 100)); perturb(model, sg)
|
| 322 |
+
v0 = fast_eval(model, "val")["score"]; trivial = v0 >= tau; T_re, hit = 1, trivial
|
| 323 |
+
if not trivial:
|
| 324 |
+
opt, scaler, rng = make_opt(model, C.lr_bb, C.lr_new, C.wd_new), make_scaler(), random.Random(999 + int(sg * 10)); T_re = C.frr_max_steps
|
| 325 |
+
for s in range(1, C.frr_max_steps + 1):
|
| 326 |
+
for g in opt.param_groups: g["lr"] = g["base_lr"] * min(1.0, s / 5)
|
| 327 |
+
sgd_step(model, opt, scaler, to_device(build_batch(sample_exs(rng, C.bs), model.tk, model.tokz, model.cfg), dev))
|
| 328 |
+
if s % C.frr_every == 0 and fast_eval(model, "val")["score"] >= tau: T_re, hit = s, True; break
|
| 329 |
+
res[sg] = dict(v0=v0, tau=tau, T_first=T_first, T_re=T_re, FRR=T_first / max(T_re, 1), L_FRR=max(T_re, 1) / max(T_first, 1),
|
| 330 |
+
censored=(not hit), trivial=trivial)
|
| 331 |
+
print(f" [FRR] sigma={sg}: perturbed score {v0:.3f} (tau {tau:.3f}) T_first={T_first} T_re={T_re}{'+' if not hit else ''} FRR={res[sg]['FRR']:.1f}")
|
| 332 |
+
model.load_state_dict(snap); return res
|
| 333 |
+
|
| 334 |
+
|
| 335 |
+
def adapt_curve(model, fam, eval_batches, steps, at):
|
| 336 |
+
"""Few-shot adaptation of a snapshot to a held-out family; returns {step: (acc, nll)}. Model is restored afterwards."""
|
| 337 |
+
snap = clone_state(model); opt, scaler, rng = make_opt(model, C.lr_bb, C.lr_new, 0.0), make_scaler(), random.Random(777); curve = {}
|
| 338 |
+
for s in range(steps + 1):
|
| 339 |
+
if s in at:
|
| 340 |
+
r = stat(predict_res(model, eval_batches), float(model.post_T)); curve[s] = (r["score"], r["nll"])
|
| 341 |
+
if s == steps: break
|
| 342 |
+
for g in opt.param_groups: g["lr"] = g["base_lr"] * min(1.0, (s + 1) / 3)
|
| 343 |
+
b = to_device(build_batch([make_example(rng, [fam], "train", "any") for _ in range(C.probe_bs)], model.tk, model.tokz, model.cfg), dev)
|
| 344 |
+
sgd_step(model, opt, scaler, b)
|
| 345 |
+
model.load_state_dict(snap); return curve
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
def meta_probe(model, step):
|
| 349 |
+
out = [dict(step=step, fam=f, curve=adapt_curve(model, f, ST["held_test"][f], C.probe_steps, C.probe_at)) for f in ST["held_fams"]]
|
| 350 |
+
msg = " | ".join(f"{o['fam']}: zs {o['curve'][0][0]:.2f} -> @10 {o['curve'][10][0]:.2f} -> @{C.probe_steps} {o['curve'][C.probe_steps][0]:.2f}" for o in out)
|
| 351 |
+
print(f" [meta-probe @ {step}] {msg}"); return out
|
| 352 |
+
|
| 353 |
+
|
| 354 |
+
# ----------------------------------------------------------------------------------------------- setup + train
|
| 355 |
+
def setup():
|
| 356 |
+
random.seed(C.seed); np.random.seed(C.seed); torch.manual_seed(C.seed)
|
| 357 |
+
load_all()
|
| 358 |
+
m = Alpha(AlphaConfig(backbone=C.backbone)).to(dev).use_data_parallel()
|
| 359 |
+
ST["model"] = m; ST["w"] = [math.sqrt(len(DATA[f]["rows"]["train"])) for f in ST["train_fams"]]
|
| 360 |
+
tf, hf = ST["train_fams"], ST["held_fams"]
|
| 361 |
+
fast = lambda split, lo, n: [make_example(random.Random(i * 31 + j), [f], split, "train", idx=i) for j, f in enumerate(tf) for i in range(lo, lo + n)]
|
| 362 |
+
ST["fast_val"], ST["fast_train"] = prep(fast("val", 0, C.fast_n)), prep(fast("train", 0, C.fast_n))
|
| 363 |
+
ST["cal"] = prep([e for f in tf for e in val_examples(f, 0, C.n_cal, "train")])
|
| 364 |
+
ST["held_test"] = {f: prep(val_examples(f, 0, C.probe_test_n, "unseen")) for f in hf}
|
| 365 |
+
rng = random.Random(4242); ST["diag"] = prep([make_example(rng, rng.sample(tf, min(3, len(tf)))) for _ in range(16)], bs=16)[0]
|
| 366 |
+
n_all = sum(p.numel() for p in m.parameters()); print(f"params: {n_all/1e6:.1f}M | GPUs: {torch.cuda.device_count()} | train fams {tf} | held-out {hf}")
|
| 367 |
+
|
| 368 |
+
|
| 369 |
+
def train():
|
| 370 |
+
m, hist = ST["model"], []; rng = random.Random(C.seed + 1)
|
| 371 |
+
ctl, mem, ema = Controller(), FMem(ST["diag"]), EMA(m, C.ema)
|
| 372 |
+
opt, scaler = make_opt(m, C.lr_bb, C.lr_new, ctl.wd), make_scaler()
|
| 373 |
+
ST.update(ctl=ctl, mem=mem, hist=hist, probes=meta_probe(m, 0)); best, lam, loss_ema, t0, mid_done = -1, C.lam_mem, None, time.time(), False
|
| 374 |
+
for step in range(1, C.steps + 1):
|
| 375 |
+
prog = max(0.0, (step - C.warmup) / max(1, C.steps - C.warmup))
|
| 376 |
+
mult = min(1.0, step / C.warmup) * (0.1 + 0.9 * 0.5 * (1 + math.cos(math.pi * prog)))
|
| 377 |
+
for g in opt.param_groups:
|
| 378 |
+
g["lr"] = g["base_lr"] * mult
|
| 379 |
+
if g["tag"] == "new": g["weight_decay"] = ctl.wd
|
| 380 |
+
b = to_device(build_batch(sample_exs(rng, C.bs), m.tk, m.tokz, m.cfg), dev)
|
| 381 |
+
nll, gn = sgd_step(m, opt, scaler, b, mem, lam, anchor=(step % C.anchor_every == 0))
|
| 382 |
+
ema.update(m, step); loss_ema = nll if loss_ema is None else 0.98 * loss_ema + 0.02 * nll
|
| 383 |
+
if step % C.eval_every == 0 or step == C.steps:
|
| 384 |
+
ema.apply(m); v, t = fast_eval(m, "val"), fast_eval(m, "train")
|
| 385 |
+
rec = dict(step=step, score=v["score"], nll=v["nll"], ece=v["ece"], tr_score=t["score"], tr_nll=t["nll"], fam=v["per_acc"],
|
| 386 |
+
wd=ctl.wd, lam=lam, gn=gn, loss=loss_ema, rho=ctl.rho, lr=opt.param_groups[0]["lr"])
|
| 387 |
+
hist.append(rec)
|
| 388 |
+
if v["score"] > best: best = v["score"]; ST["best_state"] = clone_state(m); ST["best_step"] = step
|
| 389 |
+
ctl.update(rec)
|
| 390 |
+
if step % C.mem_every == 0: mem.add(m, step, v["score"])
|
| 391 |
+
if step % C.probe_every == 0: ST["probes"] += meta_probe(m, step)
|
| 392 |
+
if not mid_done and step >= C.steps // 2:
|
| 393 |
+
mid_done = True; r = frr_test(m, hist, v["score"], [1])[1]; ctl.LFRR = r["L_FRR"]; lam = C.lam_mem * (1 + min(ctl.LFRR, 3.0))
|
| 394 |
+
print(f" [L_FRR={ctl.LFRR:.3f}] -> anchor weight {lam:.3f}")
|
| 395 |
+
ema.restore(m)
|
| 396 |
+
print(f"step {step:5d} | val acc {v['score']:.3f} nll {v['nll']:.3f} ece {v['ece']:.3f} | train acc {t['score']:.3f} nll {t['nll']:.3f} | "
|
| 397 |
+
f"rho {ctl.rho if ctl.rho is None else round(ctl.rho, 2)} wd {ctl.wd:.3f} lam {lam:.2f} gn {gn:.2f} | {time.time()-t0:.0f}s")
|
| 398 |
+
m.load_state_dict(ST["best_state"]); print(f"loaded best EMA checkpoint (step {ST['best_step']})")
|
| 399 |
+
|
| 400 |
+
|
| 401 |
+
# ----------------------------------------------------------------------------------------------- finalize + benchmark
|
| 402 |
+
def finalize():
|
| 403 |
+
m, hist = ST["model"], ST["hist"]; m.eval()
|
| 404 |
+
res = predict_res(m, ST["cal"]); grid = np.arange(0.5, 3.01, 0.02)
|
| 405 |
+
nlls = [np.mean([-(lg / T - np.logaddexp.reduce(lg / T))[g] for _, lg, g in res]) for T in grid]
|
| 406 |
+
T = float(grid[int(np.argmin(nlls))]); m.post_T.fill_(T); print(f"post-hoc temperature T={T:.2f}")
|
| 407 |
+
best = max(h["score"] for h in hist); print("FRR sweep (basin test):"); ST["frr"] = frr_test(m, hist, best, C.sigmas)
|
| 408 |
+
tau = min(h["nll"] for h in hist) + 0.05
|
| 409 |
+
Tv = next((h["step"] for h in hist if h["nll"] <= tau), hist[-1]["step"]); Tt = next((h["step"] for h in hist if h["tr_nll"] <= tau), hist[-1]["step"])
|
| 410 |
+
ST["DMR"] = dict(T_discover=Tv, T_memorize=Tt, DMR=Tv / max(Tt, 1)); print("DMR:", ST["DMR"])
|
| 411 |
+
# meta-grokking: T_D(n) = adaptation steps to reach 95% of the best adapted accuracy seen over all probes (per family)
|
| 412 |
+
P, fams, mg = ST["probes"], ST["held_fams"], {}
|
| 413 |
+
steps_ = sorted({p["step"] for p in P})
|
| 414 |
+
for f in fams:
|
| 415 |
+
tau_f = 0.95 * max(p["curve"][C.probe_steps][0] for p in P if p["fam"] == f)
|
| 416 |
+
for s in steps_:
|
| 417 |
+
c = next(p for p in P if p["fam"] == f and p["step"] == s)["curve"]
|
| 418 |
+
td = next((k for k in sorted(c) if c[k][0] >= tau_f), C.probe_steps * 2)
|
| 419 |
+
mg.setdefault(s, {})[f] = dict(T_D=max(td, 1), zero_shot=c[0][0], acc10=c[10][0], final=c[C.probe_steps][0])
|
| 420 |
+
base = steps_[0]
|
| 421 |
+
for s in steps_:
|
| 422 |
+
g = [mg[base][f]["T_D"] / mg[s][f]["T_D"] for f in fams]; mg[s]["MGR"] = float(np.exp(np.mean(np.log(g))))
|
| 423 |
+
ST["meta"] = mg; print("meta-grokking MGR by checkpoint:", {s: round(mg[s]["MGR"], 2) for s in steps_})
|
| 424 |
+
|
| 425 |
+
|
| 426 |
+
@torch.no_grad()
|
| 427 |
+
def workflow_eval(n=300, k=4):
|
| 428 |
+
m = ST["model"]; rng = random.Random(2024); exs = []
|
| 429 |
+
for _ in range(n): exs.append(make_example(rng, rng.sample(ST["train_fams"], min(k, len(ST["train_fams"]))), "val", "train", lo=C.n_cal))
|
| 430 |
+
m.eval(); qacc, allok, jc, jok = [], [], [], []
|
| 431 |
+
for i in range(0, n, 32):
|
| 432 |
+
b = to_device(build_batch(exs[i:i + 32], m.tk, m.tokz, m.cfg), dev)
|
| 433 |
+
with ac(): lg = m(b).float() / m.post_T
|
| 434 |
+
per = {}
|
| 435 |
+
for r, idx in enumerate(b["opt_lists"]):
|
| 436 |
+
p = F.softmax(lg[r, idx], -1); ok = int(p.argmax()) == b["gold_pos"][r]
|
| 437 |
+
qacc.append(ok); per.setdefault(b["q_ex"][r], []).append((ok, float(p.max())))
|
| 438 |
+
for v in per.values():
|
| 439 |
+
allok.append(all(o for o, _ in v)); jc.append(float(np.prod([c for _, c in v]))); jok.append(float(all(o for o, _ in v)))
|
| 440 |
+
return dict(q_acc=float(np.mean(qacc)), all_correct=float(np.mean(allok)), joint_ece=ece_fn(jc, jok), k=k, n=n)
|
| 441 |
+
|
| 442 |
+
|
| 443 |
+
def speed_bench():
|
| 444 |
+
m = ST["model"]; m.eval()
|
| 445 |
+
state = dict(customer_ticket="My card was charged twice for the same order and support has not replied in three days. I want my money back.",
|
| 446 |
+
account="plan: pro; tenure_months: 14; open_tickets: 2")
|
| 447 |
+
qs = [dict(id="refund", question="Does the customer ask for a refund?", options=["no", "yes"]),
|
| 448 |
+
dict(id="urgency", question="How urgent is the ticket?", options=["low", "medium", "high"], ordinal=True),
|
| 449 |
+
dict(id="team", question="Which team should handle the ticket?", options=["billing", "technical", "sales", "account", "abuse"])]
|
| 450 |
+
sync = (lambda: torch.cuda.synchronize()) if torch.cuda.is_available() else (lambda: None)
|
| 451 |
+
t = time.perf_counter(); m.predict(state, qs); sync(); cold = (time.perf_counter() - t) * 1e3
|
| 452 |
+
for _ in range(10): m.predict(state, qs)
|
| 453 |
+
ts = []
|
| 454 |
+
for _ in range(200):
|
| 455 |
+
sync(); t = time.perf_counter(); m.predict(state, qs); sync(); ts.append((time.perf_counter() - t) * 1e3)
|
| 456 |
+
rng = random.Random(1); exs = [make_example(rng, rng.sample(ST["train_fams"], 3)) for _ in range(64)]
|
| 457 |
+
with torch.no_grad():
|
| 458 |
+
for _ in range(3): m(to_device(build_batch(exs, m.tk, m.tokz, m.cfg), dev))
|
| 459 |
+
sync(); t = time.perf_counter()
|
| 460 |
+
for _ in range(10):
|
| 461 |
+
b = to_device(build_batch(exs, m.tk, m.tokz, m.cfg), dev)
|
| 462 |
+
with torch.no_grad(), ac(): m(b)
|
| 463 |
+
sync(); e2e = 10 * 64 / (time.perf_counter() - t)
|
| 464 |
+
return dict(latency_ms_p50=float(np.percentile(ts, 50)), latency_ms_p95=float(np.percentile(ts, 95)), cold_first_call_ms=cold,
|
| 465 |
+
throughput_workflows_per_s_bs64=e2e, questions_per_workflow=3, device=torch.cuda.get_device_name(0) if torch.cuda.is_available() else "cpu")
|
| 466 |
+
|
| 467 |
+
|
| 468 |
+
def llm_baseline(n_per=30, fams=("sst2", "ag_news", "emotion", "snli")):
|
| 469 |
+
"""Generative small-LLM baseline on the SAME k=1 questions (answers parsed from free text) -> accuracy + latency."""
|
| 470 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 471 |
+
fams = [f for f in fams if f in DATA]; name = C.llm_baseline
|
| 472 |
+
t = AutoTokenizer.from_pretrained(name); lm = AutoModelForCausalLM.from_pretrained(name, torch_dtype=torch.float16).to(dev).eval()
|
| 473 |
+
m = ST["model"]; m.eval(); lat, ok_l, ok_a = [], [], []
|
| 474 |
+
for f in fams:
|
| 475 |
+
for i in range(n_per):
|
| 476 |
+
ex = make_example(random.Random(i), [f], "val", "train", idx=C.n_cal + i); q = ex["questions"][0]
|
| 477 |
+
state = "\n".join(f"{k}: {v}" for k, v in ex["fields"])
|
| 478 |
+
msg = [{"role": "user", "content": f"{state}\n\nQuestion: {q['q']}\nOptions: {', '.join(q['options'])}\nReply with exactly one option and nothing else."}]
|
| 479 |
+
ids = t.apply_chat_template(msg, add_generation_prompt=True, return_tensors="pt", return_dict=True).to(dev)
|
| 480 |
+
torch.cuda.synchronize(); t0 = time.perf_counter()
|
| 481 |
+
with torch.no_grad(): out = lm.generate(**ids, max_new_tokens=12, do_sample=False, pad_token_id=t.eos_token_id)
|
| 482 |
+
torch.cuda.synchronize(); lat.append((time.perf_counter() - t0) * 1e3)
|
| 483 |
+
txt = t.decode(out[0, ids["input_ids"].shape[1]:], skip_special_tokens=True).strip().lower()
|
| 484 |
+
cand = [o for o in q["options"] if o.lower() in txt]; pred = max(cand, key=len) if cand else None
|
| 485 |
+
ok_l.append(pred is not None and pred == q["options"][q["gold"]])
|
| 486 |
+
b = to_device(build_batch([ex], m.tk, m.tokz, m.cfg), dev)
|
| 487 |
+
with torch.no_grad(), ac(): lg = m(b)
|
| 488 |
+
ok_a.append(int(lg[0, b["opt_lists"][0]].argmax()) == b["gold_pos"][0])
|
| 489 |
+
del lm; torch.cuda.empty_cache()
|
| 490 |
+
return dict(model=name, n=len(ok_l), llm_acc=float(np.mean(ok_l)), alpha_acc=float(np.mean(ok_a)), llm_latency_ms_p50=float(np.percentile(lat, 50)),
|
| 491 |
+
llm_latency_ms_p95=float(np.percentile(lat, 95)), families=fams)
|
| 492 |
+
|
| 493 |
+
|
| 494 |
+
def benchmark(run_llm=True):
|
| 495 |
+
m = ST["model"]; m.eval(); T = float(m.post_T); R = dict(post_T=T, quality={}, calib={})
|
| 496 |
+
for wording in ("train", "unseen"):
|
| 497 |
+
allr = []
|
| 498 |
+
for f in ST["train_fams"]:
|
| 499 |
+
res = predict_res(m, prep(val_examples(f, C.n_cal, C.n_cal + C.n_test, wording))); allr += res
|
| 500 |
+
s = stat(res, T)["per"][f]; R["quality"].setdefault(wording, {})[f] = {k: s[k] for k in ("acc", "nll", "ece", "brier", "n")}
|
| 501 |
+
s0, s1 = stat(allr, 1.0), stat(allr, T)
|
| 502 |
+
R["quality"][wording]["_macro"] = dict(acc=s1["score"], nll=s1["nll"], ece=s1["ece"], brier=s1["brier"])
|
| 503 |
+
R["calib"][wording] = dict(ece_before_T=s0["ece"], ece_after_T=s1["ece"], conf=s1["micro"]["conf"], corr=s1["micro"]["corr"])
|
| 504 |
+
R["held_out"] = {}
|
| 505 |
+
for f in ST["held_fams"]:
|
| 506 |
+
eb = prep(val_examples(f, C.n_cal, C.n_cal + C.n_test, "unseen"))
|
| 507 |
+
c = adapt_curve(m, f, eb, C.probe_steps, C.probe_at); R["held_out"][f] = dict(zero_shot_acc=c[0][0], adapted_acc={k: v[0] for k, v in c.items()}, n=len(val_examples(f, C.n_cal, C.n_cal + C.n_test, "unseen")))
|
| 508 |
+
R["workflow"] = workflow_eval()
|
| 509 |
+
R["speed"] = speed_bench()
|
| 510 |
+
R["type_safety"] = dict(schema_violations=0, note="outputs are a masked softmax over the declared options; an out-of-schema answer cannot be produced")
|
| 511 |
+
if run_llm:
|
| 512 |
+
try: R["llm_baseline"] = llm_baseline()
|
| 513 |
+
except Exception as e: R["llm_baseline"] = dict(error=f"{type(e).__name__}: {str(e)[:200]}")
|
| 514 |
+
R["frr"] = ST["frr"]; R["dmr"] = ST["DMR"]; R["meta"] = {str(k): v for k, v in ST["meta"].items()}
|
| 515 |
+
ST["R"] = R
|
| 516 |
+
print(json.dumps({k: v for k, v in R.items() if k not in ("calib", "meta")}, indent=1, default=float)[:6000]); return R
|
| 517 |
+
|
| 518 |
+
|
| 519 |
+
def plots(path="alpha_report.png"):
|
| 520 |
+
import matplotlib; import matplotlib.pyplot as plt
|
| 521 |
+
H, R = ST["hist"], ST["R"]; st = [h["step"] for h in H]
|
| 522 |
+
fig, ax = plt.subplots(2, 4, figsize=(22, 9)); ax = ax.ravel()
|
| 523 |
+
ax[0].plot(st, [h["score"] for h in H], label="val acc"); ax[0].plot(st, [h["tr_score"] for h in H], label="train acc"); ax[0].set_title("Learning curve (EMA weights)"); ax[0].legend()
|
| 524 |
+
ax[1].plot(st, [h["nll"] for h in H], label="val nll"); ax[1].plot(st, [h["tr_nll"] for h in H], label="train nll"); ax[1].axvline(ST["DMR"]["T_discover"], color="g", ls=":"); ax[1].axvline(ST["DMR"]["T_memorize"], color="r", ls=":")
|
| 525 |
+
ax[1].set_title(f"DMR = {ST['DMR']['DMR']:.2f} (T_discover/T_memorize)"); ax[1].legend()
|
| 526 |
+
ax[2].plot(st, [h["wd"] for h in H], label="wd (new modules)"); ax[2].plot(st, [h["rho"] if h["rho"] is not None else 0 for h in H], label="rho"); ax[2].plot(st, [h["gn"] for h in H], label="grad norm"); ax[2].legend(); ax[2].set_title("Discovery controller")
|
| 527 |
+
sg = list(R["frr"]); ax[3].bar([str(s) for s in sg], [min(R["frr"][s]["FRR"], 100) for s in sg]); ax[3].axhline(1, color="k", ls="--"); ax[3].set_yscale("log"); ax[3].set_title("FRR vs perturbation sigma (basin test)")
|
| 528 |
+
mg = ST["meta"]; ss = sorted(k for k in mg); ax[4].plot(ss, [mg[s]["MGR"] for s in ss], "o-"); ax[4].axhline(1, color="k", ls="--"); ax[4].set_title("Meta-grokking rate MGR (held-out families)")
|
| 529 |
+
for f in ST["held_fams"]: ax[5].plot(ss, [mg[s][f]["zero_shot"] for s in ss], "o-", label=f"{f} zero-shot"); ax[5].plot(ss, [mg[s][f]["acc10"] for s in ss], "s--", label=f"{f} +10 steps")
|
| 530 |
+
ax[5].legend(fontsize=7); ax[5].set_title("Unseen families: zero-shot / after 10 steps")
|
| 531 |
+
conf, corr = np.array(R["calib"]["train"]["conf"]), np.array(R["calib"]["train"]["corr"]); e = np.linspace(0, 1, 11)
|
| 532 |
+
xs, ys = [], []
|
| 533 |
+
for lo, hi in zip(e[:-1], e[1:]):
|
| 534 |
+
mk = (conf > lo) & (conf <= hi)
|
| 535 |
+
if mk.sum() > 5: xs.append(conf[mk].mean()); ys.append(corr[mk].mean())
|
| 536 |
+
ax[6].plot([0, 1], [0, 1], "k--"); ax[6].plot(xs, ys, "o-"); ax[6].set_title(f"Reliability (ECE {R['calib']['train']['ece_after_T']:.3f})")
|
| 537 |
+
fams = ST["train_fams"]; x = np.arange(len(fams))
|
| 538 |
+
ax[7].bar(x - .2, [R["quality"]["train"][f]["acc"] for f in fams], .4, label="seen wording"); ax[7].bar(x + .2, [R["quality"]["unseen"][f]["acc"] for f in fams], .4, label="unseen wording")
|
| 539 |
+
ax[7].set_xticks(x); ax[7].set_xticklabels(fams, rotation=60); ax[7].legend(); ax[7].set_title("Test accuracy per family")
|
| 540 |
+
plt.tight_layout(); plt.savefig(path, dpi=110); plt.show()
|
| 541 |
+
|
| 542 |
+
|
| 543 |
+
# ----------------------------------------------------------------------------------------------- publish
|
| 544 |
+
def get_token():
|
| 545 |
+
t = os.environ.get("HF_TOKEN")
|
| 546 |
+
if not t:
|
| 547 |
+
try:
|
| 548 |
+
from kaggle_secrets import UserSecretsClient
|
| 549 |
+
t = UserSecretsClient().get_secret("HF_TOKEN")
|
| 550 |
+
except Exception: pass
|
| 551 |
+
return t
|
| 552 |
+
|
| 553 |
+
|
| 554 |
+
def model_card(R):
|
| 555 |
+
q, sp, wf, h = R["quality"], R["speed"], R["workflow"], R["held_out"]
|
| 556 |
+
rows = "\n".join(f"| {f} | {q['train'][f]['acc']:.3f} | {q['unseen'][f]['acc']:.3f} | {q['train'][f]['ece']:.3f} |" for f in ST["train_fams"])
|
| 557 |
+
hrows = "\n".join(f"| {f} | {v['zero_shot_acc']:.3f} | {v['adapted_acc'][10]:.3f} | {v['adapted_acc'][C.probe_steps]:.3f} |" for f, v in h.items())
|
| 558 |
+
llm = R.get("llm_baseline", {}); llm_s = (f"Qwen2.5-0.5B-Instruct (generative, same {llm['n']} questions): acc {llm['llm_acc']:.3f}, p50 latency {llm['llm_latency_ms_p50']:.0f} ms "
|
| 559 |
+
f"vs Alpha acc {llm['alpha_acc']:.3f}, p50 {sp['latency_ms_p50']:.1f} ms.") if "llm_acc" in llm else "LLM baseline not run."
|
| 560 |
+
fr = " ".join(f"sigma={s}: FRR {v['FRR']:.1f}{'*' if v['censored'] else ''}" for s, v in R["frr"].items())
|
| 561 |
+
return f"""---
|
| 562 |
+
license: apache-2.0
|
| 563 |
+
base_model: {C.backbone}
|
| 564 |
+
tags: [system-one, structured-output, calibrated, classification, parallel-decoding]
|
| 565 |
+
---
|
| 566 |
+
# Alpha (System-One-style typed decision model)
|
| 567 |
+
|
| 568 |
+
Alpha takes unstructured / structured state plus **typed questions with declared options** and returns calibrated probabilities for
|
| 569 |
+
**all questions in one parallel forward pass**. It cannot generate strings and cannot answer outside the declared options
|
| 570 |
+
(masked softmax -> schema violations are impossible by construction). Option embeddings are independent of the state, so a schema can be
|
| 571 |
+
compiled once and cached; cardinality is limited only by memory.
|
| 572 |
+
|
| 573 |
+
Architecture: `{C.backbone}` encoder (state + question slots with `<mask>` readout tokens) -> 2-layer **Slot Reasoner** (set transformer, squared-ReLU,
|
| 574 |
+
zero-init residuals) -> biaffine/cosine scorer against option embeddings with per-question learned temperature + post-hoc temperature (T={R['post_T']:.2f}).
|
| 575 |
+
|
| 576 |
+
Training: {C.steps} steps x {C.bs} workflow-style examples (1-4 questions over named fields, mixed from {len(ST['train_fams'])} public datasets with paraphrased
|
| 577 |
+
questions/option wordings), proper-scoring-rule loss (NLL + Brier + ordinal term), EMA weights, functional-memory anchor, discovery controller.
|
| 578 |
+
Held-out families (never trained on): {', '.join(ST['held_fams'])}.
|
| 579 |
+
|
| 580 |
+
## Results (test splits; see results.json, alpha_report.png)
|
| 581 |
+
| family | acc (seen wording) | acc (unseen wording) | ECE |
|
| 582 |
+
|---|---|---|---|
|
| 583 |
+
{rows}
|
| 584 |
+
|
| 585 |
+
Workflow eval ({wf['k']} questions per query): per-question acc {wf['q_acc']:.3f}, all-correct {wf['all_correct']:.3f}, joint-confidence ECE {wf['joint_ece']:.3f}.
|
| 586 |
+
|
| 587 |
+
Held-out task families (unseen schema wording): zero-shot / after 10 / after {C.probe_steps} gradient steps
|
| 588 |
+
| family | zero-shot | +10 steps | +{C.probe_steps} steps |
|
| 589 |
+
|---|---|---|---|
|
| 590 |
+
{hrows}
|
| 591 |
+
|
| 592 |
+
Speed on {sp['device']}: p50 {sp['latency_ms_p50']:.1f} ms, p95 {sp['latency_ms_p95']:.1f} ms for a 3-question query (local, no network); {sp['throughput_workflows_per_s_bs64']:.0f} workflows/s at batch 64.
|
| 593 |
+
{llm_s}
|
| 594 |
+
|
| 595 |
+
Framework diagnostics: DMR={R['dmr']['DMR']:.2f}; FRR by perturbation: {fr} (* = not re-reached within budget); MGR by checkpoint in results.json.
|
| 596 |
+
|
| 597 |
+
## Honest limits
|
| 598 |
+
* This is a small research model trained on public classification datasets. **It is not a replacement for, and has not been compared against, TypeSafe's Jev**
|
| 599 |
+
(a closed API; its claims were not verified here). Do not read the latency comparison as a Jev comparison.
|
| 600 |
+
* Narrow task coverage (sentiment/topic/intent/NLI/paraphrase/spam/rating); free-form reasoning is out of scope by design.
|
| 601 |
+
* Calibration is measured in-distribution; shift will degrade it.
|
| 602 |
+
|
| 603 |
+
## Usage
|
| 604 |
+
```python
|
| 605 |
+
from huggingface_hub import snapshot_download; import sys
|
| 606 |
+
p = snapshot_download("{C.repo_id}"); sys.path.insert(0, p)
|
| 607 |
+
from alpha_s1 import Alpha
|
| 608 |
+
m = Alpha.from_pretrained(p, device="cuda").eval()
|
| 609 |
+
print(m.predict({{"ticket": "I was charged twice, refund me now."}},
|
| 610 |
+
[{{"id": "refund", "question": "Does the customer want a refund?", "options": ["no", "yes"]}}]))
|
| 611 |
+
```
|
| 612 |
+
"""
|
| 613 |
+
|
| 614 |
+
|
| 615 |
+
def publish(out_dir="alpha_out"):
|
| 616 |
+
from huggingface_hub import HfApi
|
| 617 |
+
tok = get_token(); assert tok, "Set a Kaggle secret named HF_TOKEN (Add-ons > Secrets) or env var HF_TOKEN."
|
| 618 |
+
R = ST["R"]; m = ST["model"]; m.save_pretrained(out_dir)
|
| 619 |
+
shutil.copy("alpha_s1.py", out_dir); shutil.copy("alpha_train.py", out_dir)
|
| 620 |
+
if os.path.exists("alpha_report.png"): shutil.copy("alpha_report.png", out_dir)
|
| 621 |
+
slim = {k: v for k, v in R.items() if k != "calib"}; json.dump(slim, open(f"{out_dir}/results.json", "w"), indent=1, default=float)
|
| 622 |
+
json.dump(dict(hist=ST["hist"], probes=ST["probes"]), open(f"{out_dir}/training_log.json", "w"), default=float)
|
| 623 |
+
open(f"{out_dir}/README.md", "w").write(model_card(R))
|
| 624 |
+
api = HfApi(token=tok); api.create_repo(C.repo_id, exist_ok=True, private=False)
|
| 625 |
+
api.upload_folder(folder_path=out_dir, repo_id=C.repo_id, commit_message="Alpha: System-One-style typed decision model")
|
| 626 |
+
print(f"published -> https://huggingface.co/{C.repo_id}")
|
| 627 |
+
|
| 628 |
+
|
| 629 |
+
def demo():
|
| 630 |
+
m = ST["model"]; m.eval()
|
| 631 |
+
state = dict(review="The battery died after two days and support never answered. Total waste of money.", account="plan: pro; tenure_months: 14")
|
| 632 |
+
qs = [dict(id="sentiment", question="Is the review positive or negative?", options=["negative", "positive"]),
|
| 633 |
+
dict(id="stars", question="How many stars does the review deserve?", options=["1 star", "2 stars", "3 stars", "4 stars", "5 stars"], ordinal=True),
|
| 634 |
+
dict(id="topic", question="What is the review about?", options=["hardware", "billing", "support", "shipping"])]
|
| 635 |
+
print(json.dumps(m.predict(state, qs), indent=1))
|
| 636 |
+
|
| 637 |
+
|
| 638 |
+
def chat():
|
| 639 |
+
m = ST["model"]; print("Alpha structured console. Empty text to quit.")
|
| 640 |
+
while True:
|
| 641 |
+
text = input("state text> ").strip()
|
| 642 |
+
if not text: break
|
| 643 |
+
q = input("question> ").strip(); opts = [o.strip() for o in input("options (comma separated)> ").split(",") if o.strip()]
|
| 644 |
+
r = m.predict(dict(input=text), [dict(id="q", question=q, options=opts)])["q"]
|
| 645 |
+
print(f" answer={r['answer']} confidence={r['confidence']:.3f} certainty={r['certainty']:.3f}\n probs={ {k: round(v, 3) for k, v in r['probs'].items()} }")
|
pytorch_model.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:689fdf21871e4e76390985ef67be0cd40913eec674ad1deffd626bae9cf37243
|
| 3 |
+
size 384442495
|
results.json
ADDED
|
@@ -0,0 +1,435 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"post_T": 1.0399999618530273,
|
| 3 |
+
"quality": {
|
| 4 |
+
"train": {
|
| 5 |
+
"ag_news": {
|
| 6 |
+
"acc": 0.926,
|
| 7 |
+
"nll": 0.23406508564949036,
|
| 8 |
+
"ece": 0.0323681704998016,
|
| 9 |
+
"brier": 0.11545059829950333,
|
| 10 |
+
"n": 500
|
| 11 |
+
},
|
| 12 |
+
"banking77": {
|
| 13 |
+
"acc": 0.902,
|
| 14 |
+
"nll": 0.3612114489078522,
|
| 15 |
+
"ece": 0.035957046896219286,
|
| 16 |
+
"brier": 0.15479955077171326,
|
| 17 |
+
"n": 500
|
| 18 |
+
},
|
| 19 |
+
"emotion": {
|
| 20 |
+
"acc": 0.922,
|
| 21 |
+
"nll": 0.15576711297035217,
|
| 22 |
+
"ece": 0.030244563996791818,
|
| 23 |
+
"brier": 0.08809012919664383,
|
| 24 |
+
"n": 500
|
| 25 |
+
},
|
| 26 |
+
"imdb": {
|
| 27 |
+
"acc": 0.886,
|
| 28 |
+
"nll": 0.2880212068557739,
|
| 29 |
+
"ece": 0.027435769557952863,
|
| 30 |
+
"brier": 0.1726732850074768,
|
| 31 |
+
"n": 500
|
| 32 |
+
},
|
| 33 |
+
"mrpc": {
|
| 34 |
+
"acc": 0.8217054263565892,
|
| 35 |
+
"nll": 0.3895823657512665,
|
| 36 |
+
"ece": 0.042235060486682595,
|
| 37 |
+
"brier": 0.25083833932876587,
|
| 38 |
+
"n": 258
|
| 39 |
+
},
|
| 40 |
+
"news20": {
|
| 41 |
+
"acc": 0.674,
|
| 42 |
+
"nll": 1.0884853601455688,
|
| 43 |
+
"ece": 0.06790356469154359,
|
| 44 |
+
"brier": 0.4469330608844757,
|
| 45 |
+
"n": 500
|
| 46 |
+
},
|
| 47 |
+
"sms": {
|
| 48 |
+
"acc": 0.9926470588235294,
|
| 49 |
+
"nll": 0.038313742727041245,
|
| 50 |
+
"ece": 0.0037884642096127656,
|
| 51 |
+
"brier": 0.015446269884705544,
|
| 52 |
+
"n": 408
|
| 53 |
+
},
|
| 54 |
+
"snli": {
|
| 55 |
+
"acc": 0.772,
|
| 56 |
+
"nll": 0.5716506838798523,
|
| 57 |
+
"ece": 0.045889752805233,
|
| 58 |
+
"brier": 0.3297711908817291,
|
| 59 |
+
"n": 500
|
| 60 |
+
},
|
| 61 |
+
"sst2": {
|
| 62 |
+
"acc": 0.912,
|
| 63 |
+
"nll": 0.24116064608097076,
|
| 64 |
+
"ece": 0.034141219377517684,
|
| 65 |
+
"brier": 0.14030593633651733,
|
| 66 |
+
"n": 500
|
| 67 |
+
},
|
| 68 |
+
"yelp": {
|
| 69 |
+
"acc": 0.572,
|
| 70 |
+
"nll": 0.9883294105529785,
|
| 71 |
+
"ece": 0.0719212611913681,
|
| 72 |
+
"brier": 0.5307314991950989,
|
| 73 |
+
"n": 500
|
| 74 |
+
},
|
| 75 |
+
"_macro": {
|
| 76 |
+
"acc": 0.8380352485180118,
|
| 77 |
+
"nll": 0.4356587529182434,
|
| 78 |
+
"ece": 0.01943733276175781,
|
| 79 |
+
"brier": 0.2245039939880371
|
| 80 |
+
}
|
| 81 |
+
},
|
| 82 |
+
"unseen": {
|
| 83 |
+
"ag_news": {
|
| 84 |
+
"acc": 0.924,
|
| 85 |
+
"nll": 0.25852325558662415,
|
| 86 |
+
"ece": 0.041514035522937774,
|
| 87 |
+
"brier": 0.12416581809520721,
|
| 88 |
+
"n": 500
|
| 89 |
+
},
|
| 90 |
+
"banking77": {
|
| 91 |
+
"acc": 0.89,
|
| 92 |
+
"nll": 0.4005417227745056,
|
| 93 |
+
"ece": 0.06322333976626397,
|
| 94 |
+
"brier": 0.16635079681873322,
|
| 95 |
+
"n": 500
|
| 96 |
+
},
|
| 97 |
+
"emotion": {
|
| 98 |
+
"acc": 0.894,
|
| 99 |
+
"nll": 0.38785520195961,
|
| 100 |
+
"ece": 0.12037511637806893,
|
| 101 |
+
"brier": 0.1763131022453308,
|
| 102 |
+
"n": 500
|
| 103 |
+
},
|
| 104 |
+
"imdb": {
|
| 105 |
+
"acc": 0.892,
|
| 106 |
+
"nll": 0.28929969668388367,
|
| 107 |
+
"ece": 0.023690259099006624,
|
| 108 |
+
"brier": 0.17336110770702362,
|
| 109 |
+
"n": 500
|
| 110 |
+
},
|
| 111 |
+
"mrpc": {
|
| 112 |
+
"acc": 0.8217054263565892,
|
| 113 |
+
"nll": 0.4847447872161865,
|
| 114 |
+
"ece": 0.16866437339967533,
|
| 115 |
+
"brier": 0.3047117590904236,
|
| 116 |
+
"n": 258
|
| 117 |
+
},
|
| 118 |
+
"news20": {
|
| 119 |
+
"acc": 0.678,
|
| 120 |
+
"nll": 1.0626460313796997,
|
| 121 |
+
"ece": 0.05303302364051344,
|
| 122 |
+
"brier": 0.44085004925727844,
|
| 123 |
+
"n": 500
|
| 124 |
+
},
|
| 125 |
+
"sms": {
|
| 126 |
+
"acc": 0.34558823529411764,
|
| 127 |
+
"nll": 1.1533381938934326,
|
| 128 |
+
"ece": 0.3848064363587137,
|
| 129 |
+
"brier": 0.8449604511260986,
|
| 130 |
+
"n": 408
|
| 131 |
+
},
|
| 132 |
+
"snli": {
|
| 133 |
+
"acc": 0.538,
|
| 134 |
+
"nll": 0.9769825339317322,
|
| 135 |
+
"ece": 0.11520019578933716,
|
| 136 |
+
"brier": 0.5887723565101624,
|
| 137 |
+
"n": 500
|
| 138 |
+
},
|
| 139 |
+
"sst2": {
|
| 140 |
+
"acc": 0.91,
|
| 141 |
+
"nll": 0.22101609408855438,
|
| 142 |
+
"ece": 0.02428796315193177,
|
| 143 |
+
"brier": 0.1290440559387207,
|
| 144 |
+
"n": 500
|
| 145 |
+
},
|
| 146 |
+
"yelp": {
|
| 147 |
+
"acc": 0.522,
|
| 148 |
+
"nll": 1.1097854375839233,
|
| 149 |
+
"ece": 0.09259637647867204,
|
| 150 |
+
"brier": 0.6057519912719727,
|
| 151 |
+
"n": 500
|
| 152 |
+
},
|
| 153 |
+
"_macro": {
|
| 154 |
+
"acc": 0.7415293661650708,
|
| 155 |
+
"nll": 0.6344732642173767,
|
| 156 |
+
"ece": 0.03709241313372004,
|
| 157 |
+
"brier": 0.35542815923690796
|
| 158 |
+
}
|
| 159 |
+
}
|
| 160 |
+
},
|
| 161 |
+
"held_out": {
|
| 162 |
+
"cola": {
|
| 163 |
+
"zero_shot_acc": 0.374,
|
| 164 |
+
"adapted_acc": {
|
| 165 |
+
"0": 0.374,
|
| 166 |
+
"5": 0.652,
|
| 167 |
+
"10": 0.658,
|
| 168 |
+
"20": 0.686,
|
| 169 |
+
"40": 0.686
|
| 170 |
+
},
|
| 171 |
+
"n": 500
|
| 172 |
+
},
|
| 173 |
+
"dbpedia": {
|
| 174 |
+
"zero_shot_acc": 0.312,
|
| 175 |
+
"adapted_acc": {
|
| 176 |
+
"0": 0.312,
|
| 177 |
+
"5": 0.488,
|
| 178 |
+
"10": 0.586,
|
| 179 |
+
"20": 0.876,
|
| 180 |
+
"40": 0.952
|
| 181 |
+
},
|
| 182 |
+
"n": 500
|
| 183 |
+
},
|
| 184 |
+
"offensive": {
|
| 185 |
+
"zero_shot_acc": 0.528,
|
| 186 |
+
"adapted_acc": {
|
| 187 |
+
"0": 0.528,
|
| 188 |
+
"5": 0.674,
|
| 189 |
+
"10": 0.632,
|
| 190 |
+
"20": 0.656,
|
| 191 |
+
"40": 0.694
|
| 192 |
+
},
|
| 193 |
+
"n": 500
|
| 194 |
+
}
|
| 195 |
+
},
|
| 196 |
+
"workflow": {
|
| 197 |
+
"q_acc": 0.825,
|
| 198 |
+
"all_correct": 0.43666666666666665,
|
| 199 |
+
"joint_ece": 0.10074469861705296,
|
| 200 |
+
"k": 4,
|
| 201 |
+
"n": 300
|
| 202 |
+
},
|
| 203 |
+
"speed": {
|
| 204 |
+
"latency_ms_p50": 11.066616000334761,
|
| 205 |
+
"latency_ms_p95": 13.510893649527132,
|
| 206 |
+
"cold_first_call_ms": 173.55092199977662,
|
| 207 |
+
"throughput_workflows_per_s_bs64": 354.2243768052664,
|
| 208 |
+
"questions_per_workflow": 3,
|
| 209 |
+
"device": "Tesla T4"
|
| 210 |
+
},
|
| 211 |
+
"type_safety": {
|
| 212 |
+
"schema_violations": 0,
|
| 213 |
+
"note": "outputs are a masked softmax over the declared options; an out-of-schema answer cannot be produced"
|
| 214 |
+
},
|
| 215 |
+
"llm_baseline": {
|
| 216 |
+
"model": "Qwen/Qwen2.5-0.5B-Instruct",
|
| 217 |
+
"n": 120,
|
| 218 |
+
"llm_acc": 0.5833333333333334,
|
| 219 |
+
"alpha_acc": 0.875,
|
| 220 |
+
"llm_latency_ms_p50": 82.17461200001708,
|
| 221 |
+
"llm_latency_ms_p95": 150.7793488504376,
|
| 222 |
+
"families": [
|
| 223 |
+
"sst2",
|
| 224 |
+
"ag_news",
|
| 225 |
+
"emotion",
|
| 226 |
+
"snli"
|
| 227 |
+
]
|
| 228 |
+
},
|
| 229 |
+
"frr": {
|
| 230 |
+
"0.5": {
|
| 231 |
+
"v0": 0.8416666666666666,
|
| 232 |
+
"tau": 0.83375,
|
| 233 |
+
"T_first": 4250,
|
| 234 |
+
"T_re": 1,
|
| 235 |
+
"FRR": 4250.0,
|
| 236 |
+
"L_FRR": 0.00023529411764705883,
|
| 237 |
+
"censored": false,
|
| 238 |
+
"trivial": true
|
| 239 |
+
},
|
| 240 |
+
"1": {
|
| 241 |
+
"v0": 0.8479166666666667,
|
| 242 |
+
"tau": 0.83375,
|
| 243 |
+
"T_first": 4250,
|
| 244 |
+
"T_re": 1,
|
| 245 |
+
"FRR": 4250.0,
|
| 246 |
+
"L_FRR": 0.00023529411764705883,
|
| 247 |
+
"censored": false,
|
| 248 |
+
"trivial": true
|
| 249 |
+
},
|
| 250 |
+
"2": {
|
| 251 |
+
"v0": 0.8375,
|
| 252 |
+
"tau": 0.83375,
|
| 253 |
+
"T_first": 4250,
|
| 254 |
+
"T_re": 1,
|
| 255 |
+
"FRR": 4250.0,
|
| 256 |
+
"L_FRR": 0.00023529411764705883,
|
| 257 |
+
"censored": false,
|
| 258 |
+
"trivial": true
|
| 259 |
+
},
|
| 260 |
+
"4": {
|
| 261 |
+
"v0": 0.8416666666666668,
|
| 262 |
+
"tau": 0.83375,
|
| 263 |
+
"T_first": 4250,
|
| 264 |
+
"T_re": 1,
|
| 265 |
+
"FRR": 4250.0,
|
| 266 |
+
"L_FRR": 0.00023529411764705883,
|
| 267 |
+
"censored": false,
|
| 268 |
+
"trivial": true
|
| 269 |
+
},
|
| 270 |
+
"8": {
|
| 271 |
+
"v0": 0.7979166666666667,
|
| 272 |
+
"tau": 0.83375,
|
| 273 |
+
"T_first": 4250,
|
| 274 |
+
"T_re": 300,
|
| 275 |
+
"FRR": 14.166666666666666,
|
| 276 |
+
"L_FRR": 0.07058823529411765,
|
| 277 |
+
"censored": true,
|
| 278 |
+
"trivial": false
|
| 279 |
+
}
|
| 280 |
+
},
|
| 281 |
+
"dmr": {
|
| 282 |
+
"T_discover": 3250,
|
| 283 |
+
"T_memorize": 3000,
|
| 284 |
+
"DMR": 1.0833333333333333
|
| 285 |
+
},
|
| 286 |
+
"meta": {
|
| 287 |
+
"0": {
|
| 288 |
+
"cola": {
|
| 289 |
+
"T_D": 5,
|
| 290 |
+
"zero_shot": 0.46,
|
| 291 |
+
"acc10": 0.665,
|
| 292 |
+
"final": 0.665
|
| 293 |
+
},
|
| 294 |
+
"dbpedia": {
|
| 295 |
+
"T_D": 80,
|
| 296 |
+
"zero_shot": 0.115,
|
| 297 |
+
"acc10": 0.045,
|
| 298 |
+
"final": 0.045
|
| 299 |
+
},
|
| 300 |
+
"offensive": {
|
| 301 |
+
"T_D": 80,
|
| 302 |
+
"zero_shot": 0.645,
|
| 303 |
+
"acc10": 0.64,
|
| 304 |
+
"final": 0.64
|
| 305 |
+
},
|
| 306 |
+
"MGR": 1.0
|
| 307 |
+
},
|
| 308 |
+
"1000": {
|
| 309 |
+
"cola": {
|
| 310 |
+
"T_D": 5,
|
| 311 |
+
"zero_shot": 0.55,
|
| 312 |
+
"acc10": 0.635,
|
| 313 |
+
"final": 0.665
|
| 314 |
+
},
|
| 315 |
+
"dbpedia": {
|
| 316 |
+
"T_D": 40,
|
| 317 |
+
"zero_shot": 0.34,
|
| 318 |
+
"acc10": 0.525,
|
| 319 |
+
"final": 0.93
|
| 320 |
+
},
|
| 321 |
+
"offensive": {
|
| 322 |
+
"T_D": 40,
|
| 323 |
+
"zero_shot": 0.64,
|
| 324 |
+
"acc10": 0.64,
|
| 325 |
+
"final": 0.745
|
| 326 |
+
},
|
| 327 |
+
"MGR": 1.5874010519681994
|
| 328 |
+
},
|
| 329 |
+
"2000": {
|
| 330 |
+
"cola": {
|
| 331 |
+
"T_D": 20,
|
| 332 |
+
"zero_shot": 0.4,
|
| 333 |
+
"acc10": 0.61,
|
| 334 |
+
"final": 0.665
|
| 335 |
+
},
|
| 336 |
+
"dbpedia": {
|
| 337 |
+
"T_D": 40,
|
| 338 |
+
"zero_shot": 0.305,
|
| 339 |
+
"acc10": 0.7,
|
| 340 |
+
"final": 0.955
|
| 341 |
+
},
|
| 342 |
+
"offensive": {
|
| 343 |
+
"T_D": 40,
|
| 344 |
+
"zero_shot": 0.625,
|
| 345 |
+
"acc10": 0.69,
|
| 346 |
+
"final": 0.755
|
| 347 |
+
},
|
| 348 |
+
"MGR": 1.0
|
| 349 |
+
},
|
| 350 |
+
"3000": {
|
| 351 |
+
"cola": {
|
| 352 |
+
"T_D": 10,
|
| 353 |
+
"zero_shot": 0.4,
|
| 354 |
+
"acc10": 0.665,
|
| 355 |
+
"final": 0.665
|
| 356 |
+
},
|
| 357 |
+
"dbpedia": {
|
| 358 |
+
"T_D": 40,
|
| 359 |
+
"zero_shot": 0.245,
|
| 360 |
+
"acc10": 0.64,
|
| 361 |
+
"final": 0.975
|
| 362 |
+
},
|
| 363 |
+
"offensive": {
|
| 364 |
+
"T_D": 80,
|
| 365 |
+
"zero_shot": 0.59,
|
| 366 |
+
"acc10": 0.685,
|
| 367 |
+
"final": 0.65
|
| 368 |
+
},
|
| 369 |
+
"MGR": 1.0
|
| 370 |
+
},
|
| 371 |
+
"4000": {
|
| 372 |
+
"cola": {
|
| 373 |
+
"T_D": 5,
|
| 374 |
+
"zero_shot": 0.41,
|
| 375 |
+
"acc10": 0.665,
|
| 376 |
+
"final": 0.665
|
| 377 |
+
},
|
| 378 |
+
"dbpedia": {
|
| 379 |
+
"T_D": 40,
|
| 380 |
+
"zero_shot": 0.305,
|
| 381 |
+
"acc10": 0.71,
|
| 382 |
+
"final": 0.975
|
| 383 |
+
},
|
| 384 |
+
"offensive": {
|
| 385 |
+
"T_D": 40,
|
| 386 |
+
"zero_shot": 0.57,
|
| 387 |
+
"acc10": 0.625,
|
| 388 |
+
"final": 0.74
|
| 389 |
+
},
|
| 390 |
+
"MGR": 1.5874010519681994
|
| 391 |
+
},
|
| 392 |
+
"5000": {
|
| 393 |
+
"cola": {
|
| 394 |
+
"T_D": 5,
|
| 395 |
+
"zero_shot": 0.4,
|
| 396 |
+
"acc10": 0.665,
|
| 397 |
+
"final": 0.665
|
| 398 |
+
},
|
| 399 |
+
"dbpedia": {
|
| 400 |
+
"T_D": 40,
|
| 401 |
+
"zero_shot": 0.355,
|
| 402 |
+
"acc10": 0.68,
|
| 403 |
+
"final": 0.945
|
| 404 |
+
},
|
| 405 |
+
"offensive": {
|
| 406 |
+
"T_D": 80,
|
| 407 |
+
"zero_shot": 0.575,
|
| 408 |
+
"acc10": 0.635,
|
| 409 |
+
"final": 0.715
|
| 410 |
+
},
|
| 411 |
+
"MGR": 1.2599210498948732
|
| 412 |
+
},
|
| 413 |
+
"6000": {
|
| 414 |
+
"cola": {
|
| 415 |
+
"T_D": 10,
|
| 416 |
+
"zero_shot": 0.395,
|
| 417 |
+
"acc10": 0.665,
|
| 418 |
+
"final": 0.665
|
| 419 |
+
},
|
| 420 |
+
"dbpedia": {
|
| 421 |
+
"T_D": 40,
|
| 422 |
+
"zero_shot": 0.355,
|
| 423 |
+
"acc10": 0.695,
|
| 424 |
+
"final": 0.94
|
| 425 |
+
},
|
| 426 |
+
"offensive": {
|
| 427 |
+
"T_D": 40,
|
| 428 |
+
"zero_shot": 0.555,
|
| 429 |
+
"acc10": 0.66,
|
| 430 |
+
"final": 0.77
|
| 431 |
+
},
|
| 432 |
+
"MGR": 1.2599210498948732
|
| 433 |
+
}
|
| 434 |
+
}
|
| 435 |
+
}
|
tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_prefix_space": false,
|
| 3 |
+
"backend": "tokenizers",
|
| 4 |
+
"bos_token": "<s>",
|
| 5 |
+
"cls_token": "<s>",
|
| 6 |
+
"eos_token": "</s>",
|
| 7 |
+
"errors": "replace",
|
| 8 |
+
"is_local": false,
|
| 9 |
+
"local_files_only": false,
|
| 10 |
+
"mask_token": "<mask>",
|
| 11 |
+
"model_max_length": 512,
|
| 12 |
+
"pad_token": "<pad>",
|
| 13 |
+
"sep_token": "</s>",
|
| 14 |
+
"tokenizer_class": "RobertaTokenizer",
|
| 15 |
+
"trim_offsets": true,
|
| 16 |
+
"unk_token": "<unk>"
|
| 17 |
+
}
|
training_log.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"hist": [{"step": 250, "score": 0.42499999999999993, "nll": 1.3864185810089111, "ece": 0.07763973646021138, "tr_score": 0.4333333333333333, "tr_nll": 1.3839653730392456, "fam": {"ag_news": 0.8333333333333334, "banking77": 0.0, "emotion": 0.3958333333333333, "imdb": 0.5, "mrpc": 0.6666666666666666, "news20": 0.125, "sms": 0.8958333333333334, "snli": 0.22916666666666666, "sst2": 0.4583333333333333, "yelp": 0.14583333333333334}, "wd": 0.5, "lam": 0.3, "gn": 4.74530553817749, "loss": 1.4470987440866285, "rho": null, "lr": 4.166666666666667e-05}, {"step": 500, "score": 0.4875, "nll": 1.2226603031158447, "ece": 0.059230080638856944, "tr_score": 0.4645833333333333, "tr_nll": 1.2430381774902344, "fam": {"ag_news": 0.9583333333333334, "banking77": 0.0625, "emotion": 0.3958333333333333, "imdb": 0.5, "mrpc": 0.7291666666666666, "news20": 0.2916666666666667, "sms": 1.0, "snli": 0.375, "sst2": 0.4583333333333333, "yelp": 0.10416666666666667}, "wd": 0.5, "lam": 0.3, "gn": 4.94678258895874, "loss": 1.3388411353066019, "rho": null, "lr": 4.986344023965386e-05}, {"step": 750, "score": 0.5041666666666667, "nll": 1.1497793197631836, "ece": 0.05984721723943949, "tr_score": 0.4937500000000001, "tr_nll": 1.1202466487884521, "fam": {"ag_news": 0.8958333333333334, "banking77": 0.25, "emotion": 0.3958333333333333, "imdb": 0.5208333333333334, "mrpc": 0.6458333333333334, "news20": 0.3541666666666667, "sms": 1.0, "snli": 0.375, "sst2": 0.4583333333333333, "yelp": 0.14583333333333334}, "wd": 0.45, "lam": 0.3, "gn": 3.086398124694824, "loss": 1.2649021407320382, "rho": 1.1620062206951038, "lr": 4.931150598363494e-05}, {"step": 1000, "score": 0.6145833333333333, "nll": 0.9992086291313171, "ece": 0.08922299118712546, "tr_score": 0.5999999999999999, "tr_nll": 0.9506429433822632, "fam": {"ag_news": 0.9583333333333334, "banking77": 0.2916666666666667, "emotion": 0.5625, "imdb": 0.7708333333333334, "mrpc": 0.6666666666666666, "news20": 0.4791666666666667, "sms": 1.0, "snli": 0.25, "sst2": 0.7708333333333334, "yelp": 0.3958333333333333}, "wd": 0.405, "lam": 0.3, "gn": 7.461432456970215, "loss": 1.1085828546282157, "rho": 0.8777702575734148, "lr": 4.834611651233304e-05}, {"step": 1250, "score": 0.7041666666666667, "nll": 0.7773005366325378, "ece": 0.060513773995141164, "tr_score": 0.6979166666666666, "tr_nll": 0.7319567203521729, "fam": {"ag_news": 0.9166666666666666, "banking77": 0.3958333333333333, "emotion": 0.8333333333333334, "imdb": 0.8333333333333334, "mrpc": 0.7083333333333334, "news20": 0.5416666666666666, "sms": 0.9791666666666666, "snli": 0.4166666666666667, "sst2": 0.9375, "yelp": 0.4791666666666667}, "wd": 0.36450000000000005, "lam": 0.3, "gn": 4.511319160461426, "loss": 0.87960810418064, "rho": 0.8827748724431335, "lr": 4.6985571585149876e-05}, {"step": 1500, "score": 0.7229166666666667, "nll": 0.6783604025840759, "ece": 0.036758976274480416, "tr_score": 0.7374999999999999, "tr_nll": 0.627739429473877, "fam": {"ag_news": 0.9583333333333334, "banking77": 0.5208333333333334, "emotion": 0.9166666666666666, "imdb": 0.8541666666666666, "mrpc": 0.6875, "news20": 0.5625, "sms": 1.0, "snli": 0.22916666666666666, "sst2": 0.9583333333333334, "yelp": 0.5416666666666666}, "wd": 0.32805000000000006, "lam": 0.3, "gn": 7.843607425689697, "loss": 0.8132543158575171, "rho": 0.9487538569865493, "lr": 4.5255661461418854e-05}, {"step": 1750, "score": 0.7458333333333333, "nll": 0.6375653743743896, "ece": 0.03906969136248029, "tr_score": 0.75625, "tr_nll": 0.5771324038505554, "fam": {"ag_news": 0.9166666666666666, "banking77": 0.625, "emotion": 0.8958333333333334, "imdb": 0.8541666666666666, "mrpc": 0.7291666666666666, "news20": 0.5833333333333334, "sms": 1.0, "snli": 0.3125, "sst2": 0.9791666666666666, "yelp": 0.5625}, "wd": 0.2952450000000001, "lam": 0.3, "gn": 7.016384601593018, "loss": 0.7663959374513087, "rho": 0.9490588800899795, "lr": 4.3189178024614896e-05}, {"step": 2000, "score": 0.7729166666666666, "nll": 0.5967954397201538, "ece": 0.025282762618735424, "tr_score": 0.7583333333333333, "tr_nll": 0.5407644510269165, "fam": {"ag_news": 0.9166666666666666, "banking77": 0.7291666666666666, "emotion": 0.9166666666666666, "imdb": 0.875, "mrpc": 0.7291666666666666, "news20": 0.5833333333333334, "sms": 1.0, "snli": 0.3958333333333333, "sst2": 0.9583333333333334, "yelp": 0.625}, "wd": 0.2657205000000001, "lam": 0.3, "gn": 9.855315208435059, "loss": 0.7069250917348392, "rho": 0.87758640404572, "lr": 4.0825293184962056e-05}, {"step": 2250, "score": 0.7875, "nll": 0.5712440013885498, "ece": 0.04493665626893442, "tr_score": 0.75625, "tr_nll": 0.5333563685417175, "fam": {"ag_news": 0.9166666666666666, "banking77": 0.8125, "emotion": 0.8958333333333334, "imdb": 0.8541666666666666, "mrpc": 0.75, "news20": 0.5416666666666666, "sms": 1.0, "snli": 0.4791666666666667, "sst2": 0.9583333333333334, "yelp": 0.6666666666666666}, "wd": 0.23914845000000007, "lam": 0.3, "gn": 8.997612953186035, "loss": 0.6946176960095765, "rho": 0.9993132683013181, "lr": 3.8208816343334156e-05}, {"step": 2500, "score": 0.8104166666666666, "nll": 0.5312714576721191, "ece": 0.05300602965677776, "tr_score": 0.78125, "tr_nll": 0.5068899393081665, "fam": {"ag_news": 0.9583333333333334, "banking77": 0.7916666666666666, "emotion": 0.875, "imdb": 0.8541666666666666, "mrpc": 0.7708333333333334, "news20": 0.5833333333333334, "sms": 1.0, "snli": 0.5833333333333334, "sst2": 1.0, "yelp": 0.6875}, "wd": 0.21523360500000008, "lam": 0.3, "gn": 8.83574390411377, "loss": 0.6346616129986626, "rho": 1.499656634150659, "lr": 3.5389344991836974e-05}, {"step": 2750, "score": 0.8083333333333332, "nll": 0.49808335304260254, "ece": 0.04100577929057176, "tr_score": 0.7875, "tr_nll": 0.47457775473594666, "fam": {"ag_news": 0.9583333333333334, "banking77": 0.7708333333333334, "emotion": 0.875, "imdb": 0.8541666666666666, "mrpc": 0.75, "news20": 0.6041666666666666, "sms": 1.0, "snli": 0.6875, "sst2": 0.9583333333333334, "yelp": 0.625}, "wd": 0.19371024450000007, "lam": 0.3, "gn": 6.362133979797363, "loss": 0.58079190026933, "rho": 1.5049839023584053, "lr": 3.242032455214346e-05}, {"step": 3000, "score": 0.8291666666666666, "nll": 0.47499704360961914, "ece": 0.04109802747455738, "tr_score": 0.8020833333333333, "tr_nll": 0.4411352574825287, "fam": {"ag_news": 0.9583333333333334, "banking77": 0.8333333333333334, "emotion": 0.8958333333333334, "imdb": 0.875, "mrpc": 0.7916666666666666, "news20": 0.625, "sms": 1.0, "snli": 0.75, "sst2": 0.9375, "yelp": 0.625}, "wd": 0.17433922005000008, "lam": 0.3, "gn": 9.050947189331055, "loss": 0.5507215846613893, "rho": 1.2660459721916015, "lr": 2.9358035273127483e-05}, {"step": 3250, "score": 0.8229166666666667, "nll": 0.45618176460266113, "ece": 0.03542887705067793, "tr_score": 0.8125, "tr_nll": 0.4283953309059143, "fam": {"ag_news": 0.9375, "banking77": 0.875, "emotion": 0.9166666666666666, "imdb": 0.8541666666666666, "mrpc": 0.7708333333333334, "news20": 0.6041666666666666, "sms": 1.0, "snli": 0.7291666666666666, "sst2": 0.9166666666666666, "yelp": 0.625}, "wd": 0.15690529804500009, "lam": 0.3001, "gn": 7.896519184112549, "loss": 0.5361467864703793, "rho": 0.9781872430895555, "lr": 2.6260525391993023e-05}, {"step": 3500, "score": 0.8229166666666666, "nll": 0.44824162125587463, "ece": 0.04027308725441499, "tr_score": 0.8333333333333333, "tr_nll": 0.41801562905311584, "fam": {"ag_news": 0.9166666666666666, "banking77": 0.8541666666666666, "emotion": 0.9166666666666666, "imdb": 0.8541666666666666, "mrpc": 0.7916666666666666, "news20": 0.5833333333333334, "sms": 1.0, "snli": 0.7708333333333334, "sst2": 0.9375, "yelp": 0.6041666666666666}, "wd": 0.14121476824050008, "lam": 0.3001, "gn": 7.859862804412842, "loss": 0.5212966933069149, "rho": 1.2275311193516978, "lr": 2.3186510781715892e-05}, {"step": 3750, "score": 0.825, "nll": 0.44514527916908264, "ece": 0.0378269159855942, "tr_score": 0.8416666666666668, "tr_nll": 0.41067466139793396, "fam": {"ag_news": 0.9166666666666666, "banking77": 0.8333333333333334, "emotion": 0.9375, "imdb": 0.8541666666666666, "mrpc": 0.7708333333333334, "news20": 0.5833333333333334, "sms": 1.0, "snli": 0.7708333333333334, "sst2": 0.9375, "yelp": 0.6458333333333334}, "wd": 0.12709329141645007, "lam": 0.3001, "gn": 4.868711471557617, "loss": 0.5031073578348193, "rho": 0.9962497321208292, "lr": 2.0194261942894628e-05}, {"step": 4000, "score": 0.83125, "nll": 0.43428102135658264, "ece": 0.04779160485292472, "tr_score": 0.8479166666666667, "tr_nll": 0.4039950370788574, "fam": {"ag_news": 0.9375, "banking77": 0.8333333333333334, "emotion": 0.9375, "imdb": 0.8541666666666666, "mrpc": 0.7708333333333334, "news20": 0.6458333333333334, "sms": 1.0, "snli": 0.75, "sst2": 0.9375, "yelp": 0.6458333333333334}, "wd": 0.12709329141645007, "lam": 0.3001, "gn": 6.261903762817383, "loss": 0.5046875660977973, "rho": 0.709019548630384, "lr": 1.7340499438004994e-05}, {"step": 4250, "score": 0.8375, "nll": 0.4272522032260895, "ece": 0.037357999570667745, "tr_score": 0.8416666666666666, "tr_nll": 0.397662878036499, "fam": {"ag_news": 0.9375, "banking77": 0.8541666666666666, "emotion": 0.9375, "imdb": 0.8541666666666666, "mrpc": 0.7916666666666666, "news20": 0.6458333333333334, "sms": 1.0, "snli": 0.75, "sst2": 0.9583333333333334, "yelp": 0.6458333333333334}, "wd": 0.11438396227480506, "lam": 0.3001, "gn": 10.974567413330078, "loss": 0.47385876453106374, "rho": 1.167748460619184, "lr": 1.4679318706019013e-05}, {"step": 4500, "score": 0.8375, "nll": 0.42399367690086365, "ece": 0.038577316980808976, "tr_score": 0.84375, "tr_nll": 0.39106932282447815, "fam": {"ag_news": 0.9583333333333334, "banking77": 0.8541666666666666, "emotion": 0.9166666666666666, "imdb": 0.8541666666666666, "mrpc": 0.7916666666666666, "news20": 0.6666666666666666, "sms": 1.0, "snli": 0.75, "sst2": 0.9583333333333334, "yelp": 0.625}, "wd": 0.10294556604732455, "lam": 0.3001, "gn": 6.629716396331787, "loss": 0.4687045077363484, "rho": 1.1388838315746999, "lr": 1.2261164638420832e-05}, {"step": 4750, "score": 0.8395833333333332, "nll": 0.42487725615501404, "ece": 0.034516340897728995, "tr_score": 0.84375, "tr_nll": 0.38701558113098145, "fam": {"ag_news": 0.9583333333333334, "banking77": 0.875, "emotion": 0.9375, "imdb": 0.8541666666666666, "mrpc": 0.7916666666666666, "news20": 0.6458333333333334, "sms": 1.0, "snli": 0.7291666666666666, "sst2": 0.9583333333333334, "yelp": 0.6458333333333334}, "wd": 0.0926510094425921, "lam": 0.3001, "gn": 7.820315361022949, "loss": 0.45272200221767106, "rho": 0.8165412590434078, "lr": 1.013187535438278e-05}, {"step": 5000, "score": 0.8395833333333332, "nll": 0.4237828850746155, "ece": 0.0383824546821416, "tr_score": 0.8458333333333334, "tr_nll": 0.3849530816078186, "fam": {"ag_news": 0.9583333333333334, "banking77": 0.875, "emotion": 0.9375, "imdb": 0.875, "mrpc": 0.7916666666666666, "news20": 0.625, "sms": 1.0, "snli": 0.7291666666666666, "sst2": 0.9583333333333334, "yelp": 0.6458333333333334}, "wd": 0.11581376180324011, "lam": 0.3001, "gn": 6.347634315490723, "loss": 0.4564408298368683, "rho": 0.2992874578055718, "lr": 8.331813301137644e-06}, {"step": 5250, "score": 0.8395833333333332, "nll": 0.4211656451225281, "ece": 0.04211962077145778, "tr_score": 0.8541666666666667, "tr_nll": 0.378847599029541, "fam": {"ag_news": 0.9583333333333334, "banking77": 0.875, "emotion": 0.9375, "imdb": 0.8541666666666666, "mrpc": 0.7916666666666666, "news20": 0.6458333333333334, "sms": 1.0, "snli": 0.7291666666666666, "sst2": 0.9583333333333334, "yelp": 0.6458333333333334}, "wd": 0.11581376180324011, "lam": 0.3001, "gn": 6.547802448272705, "loss": 0.4516936281062966, "rho": 0.4149458703356097, "lr": 6.8951001502612065e-06}, {"step": 5500, "score": 0.8416666666666666, "nll": 0.419617235660553, "ece": 0.04883364103734491, "tr_score": 0.85, "tr_nll": 0.37390393018722534, "fam": {"ag_news": 0.9583333333333334, "banking77": 0.875, "emotion": 0.9375, "imdb": 0.875, "mrpc": 0.7916666666666666, "news20": 0.6458333333333334, "sms": 1.0, "snli": 0.7291666666666666, "sst2": 0.9583333333333334, "yelp": 0.6458333333333334}, "wd": 0.11581376180324011, "lam": 0.3001, "gn": 7.733129501342773, "loss": 0.43449673415669426, "rho": 0.42180815916788295, "lr": 5.8489699930418664e-06}, {"step": 5750, "score": 0.84375, "nll": 0.41734427213668823, "ece": 0.042368609768648896, "tr_score": 0.8479166666666668, "tr_nll": 0.37107983231544495, "fam": {"ag_news": 0.9375, "banking77": 0.875, "emotion": 0.9375, "imdb": 0.875, "mrpc": 0.7916666666666666, "news20": 0.6666666666666666, "sms": 1.0, "snli": 0.7291666666666666, "sst2": 0.9583333333333334, "yelp": 0.6666666666666666}, "wd": 0.11581376180324011, "lam": 0.3001, "gn": 9.12564754486084, "loss": 0.430490410395239, "rho": 0.3675093773257097, "lr": 5.213253095656177e-06}, {"step": 6000, "score": 0.84375, "nll": 0.4162411093711853, "ece": 0.04647985563303032, "tr_score": 0.8458333333333334, "tr_nll": 0.36772745847702026, "fam": {"ag_news": 0.9583333333333334, "banking77": 0.875, "emotion": 0.9375, "imdb": 0.875, "mrpc": 0.7708333333333334, "news20": 0.6666666666666666, "sms": 1.0, "snli": 0.7291666666666666, "sst2": 0.9583333333333334, "yelp": 0.6666666666666666}, "wd": 0.11581376180324011, "lam": 0.3001, "gn": 8.71489429473877, "loss": 0.4269631357885679, "rho": 0.5861776263692953, "lr": 5e-06}], "probes": [{"step": 0, "fam": "cola", "curve": {"0": [0.46, 0.6933133602142334], "5": [0.665, 0.6618085503578186], "10": [0.665, 0.6377608776092529], "20": [0.665, 0.6427217721939087], "40": [0.665, 0.6488895416259766]}}, {"step": 0, "fam": "dbpedia", "curve": {"0": [0.115, 2.635910749435425], "5": [0.045, 2.6632566452026367], "10": [0.045, 2.696634531021118], "20": [0.045, 2.638427734375], "40": [0.045, 2.638758897781372]}}, {"step": 0, "fam": "offensive", "curve": {"0": [0.645, 0.6905834674835205], "5": [0.64, 0.6852070093154907], "10": [0.64, 0.6692162156105042], "20": [0.64, 0.6649163961410522], "40": [0.64, 0.7305782437324524]}}, {"step": 1000, "fam": "cola", "curve": {"0": [0.55, 0.6800724864006042], "5": [0.665, 0.6440149545669556], "10": [0.635, 0.6801218390464783], "20": [0.665, 0.6502220630645752], "40": [0.665, 0.6403223276138306]}}, {"step": 1000, "fam": "dbpedia", "curve": {"0": [0.34, 2.2151966094970703], "5": [0.45, 1.7422538995742798], "10": [0.525, 1.1715236902236938], "20": [0.795, 0.5880295634269714], "40": [0.93, 0.17617054283618927]}}, {"step": 1000, "fam": "offensive", "curve": {"0": [0.64, 0.6211206912994385], "5": [0.66, 0.6001800298690796], "10": [0.64, 0.6511775851249695], "20": [0.665, 0.7224280834197998], "40": [0.745, 1.5302973985671997]}}, {"step": 2000, "fam": "cola", "curve": {"0": [0.4, 1.2561464309692383], "5": [0.355, 1.106208324432373], "10": [0.61, 0.6751940846443176], "20": [0.665, 0.6598563194274902], "40": [0.665, 0.6479304432868958]}}, {"step": 2000, "fam": "dbpedia", "curve": {"0": [0.305, 2.196328639984131], "5": [0.575, 1.3923637866973877], "10": [0.7, 0.8865454792976379], "20": [0.86, 0.5139257311820984], "40": [0.955, 0.13148292899131775]}}, {"step": 2000, "fam": "offensive", "curve": {"0": [0.625, 0.6901967525482178], "5": [0.655, 0.6434993743896484], "10": [0.69, 0.5594972372055054], "20": [0.71, 0.6698970198631287], "40": [0.755, 0.5170150995254517]}}, {"step": 3000, "fam": "cola", "curve": {"0": [0.4, 1.342832326889038], "5": [0.62, 0.6754884123802185], "10": [0.665, 0.6443837881088257], "20": [0.665, 0.6436806321144104], "40": [0.665, 0.6559992432594299]}}, {"step": 3000, "fam": "dbpedia", "curve": {"0": [0.245, 2.18424916267395], "5": [0.455, 1.5412259101867676], "10": [0.64, 1.0229398012161255], "20": [0.885, 0.5090384483337402], "40": [0.975, 0.0869322121143341]}}, {"step": 3000, "fam": "offensive", "curve": {"0": [0.59, 0.8314429521560669], "5": [0.66, 0.8946431875228882], "10": [0.685, 0.6292023062705994], "20": [0.68, 0.6085357069969177], "40": [0.65, 0.5966840982437134]}}, {"step": 4000, "fam": "cola", "curve": {"0": [0.41, 1.2136904001235962], "5": [0.635, 0.6475875973701477], "10": [0.665, 0.6374750733375549], "20": [0.665, 0.6445882320404053], "40": [0.665, 0.6596666574478149]}}, {"step": 4000, "fam": "dbpedia", "curve": {"0": [0.305, 2.2257626056671143], "5": [0.575, 1.4236860275268555], "10": [0.71, 0.984937310218811], "20": [0.845, 0.6737918853759766], "40": [0.975, 0.105534628033638]}}, {"step": 4000, "fam": "offensive", "curve": {"0": [0.57, 0.8187274932861328], "5": [0.595, 0.7490072846412659], "10": [0.625, 0.72652268409729], "20": [0.645, 0.619418740272522], "40": [0.74, 0.8135643005371094]}}, {"step": 5000, "fam": "cola", "curve": {"0": [0.4, 1.2741897106170654], "5": [0.64, 0.6492821574211121], "10": [0.665, 0.6398915648460388], "20": [0.665, 0.6444342136383057], "40": [0.665, 0.6411840319633484]}}, {"step": 5000, "fam": "dbpedia", "curve": {"0": [0.355, 2.148179531097412], "5": [0.585, 1.378219485282898], "10": [0.68, 1.0227428674697876], "20": [0.87, 0.4382198750972748], "40": [0.945, 0.20549844205379486]}}, {"step": 5000, "fam": "offensive", "curve": {"0": [0.575, 0.9428966045379639], "5": [0.675, 0.7043898701667786], "10": [0.635, 0.6242003440856934], "20": [0.695, 0.5720301270484924], "40": [0.715, 0.5336439609527588]}}, {"step": 6000, "fam": "cola", "curve": {"0": [0.395, 1.3663846254348755], "5": [0.625, 0.6492061018943787], "10": [0.665, 0.6497192978858948], "20": [0.665, 0.6383249759674072], "40": [0.665, 0.6384083032608032]}}, {"step": 6000, "fam": "dbpedia", "curve": {"0": [0.355, 2.106869697570801], "5": [0.435, 1.3792909383773804], "10": [0.695, 1.0408819913864136], "20": [0.895, 0.3912413418292999], "40": [0.94, 0.190094992518425]}}, {"step": 6000, "fam": "offensive", "curve": {"0": [0.555, 0.9884564280509949], "5": [0.65, 0.7950121164321899], "10": [0.66, 0.5845534801483154], "20": [0.695, 0.9688383340835571], "40": [0.77, 0.5907872319221497]}}]}
|