← все исследования
технические записки · эксперимент · 2026-05-26

Self-Distilled HEAD-T: фильтр как учитель

Аннотация

Cascade-v3 + ledger.perception_filter работает: модель предлагает, фильтр отбраковывает. Но в среднем 35% учительских меток (от агентного gold) разойдутся с правилами фильтра — то есть модель училась на «over-labeled» данных. Эксперимент v4: применить фильтр как deterministic label-corrector — где он сказал бы «не на доску», переписать gold в none. Гипотеза: HEAD-T v4 будет калиброванно абстиниться, fewer demotions на инференсе. Результат — измеряется.

1. Что чиним

Гейт прошёл на cascade-v3 благодаря фильтру: модель раздаёт type=action на сомнительных репликах, а фильтр их отбраковывает (29 false-positive action на gold-none → демоут). Это работает, но тратит inference-такты на предложения, которые всё равно умрут на фильтре.

Идея: подравнять обучение к правилам фильтра. Если фильтр говорит «без императива и без адресата это не action», то и модель должна абстиниться. Это сужает расхождение model↔filter и делает каскад эффективнее.

2. Метод

Правила perception_filter — детерминированные, применимы offline:

for each (reply, gold_type) in train:
    if filter_would_keep(gold_type, reply) == False:
        gold_type ← "none"   # relabel

То есть: gold-action без императива / без адресата → переписан в none. Gold-topic короче 12 слов без named-entity → none. И так далее, по тем же правилам, что в admit().

3. Что получилось на корпусе

| metric | значение | |---|---| | Train examples | 18,880 | | Filter согласен с учителем (kept) | 12,263 | | Filter РАЗОШЁЛСЯ → relabel в none | 6,617 (35%) | | из них action | 2,961 (учитель over-fired) | | из них topic | 2,410 | | из них decision | 749 | | из них fragment | 497 |

Балансировка (та же MULT, topic×1 decision×4 action×2 fragment×4 none×1) даёт 18,847 sampled примеров:

none стало больше; decision/fragment сильно урезаны — это и есть «фильтр-как-учитель» в действии.

4. Обучение

Тот же LoRA-рецепт, что v3 (Qwen3-1.7B, r=8 layers=8, lr 1e-4, mask-prompt, 900 iters). Адаптер: adapters_headT_v4_selfdistill.

Val loss с iter 1 = 6.198 (выше v3's 2.749 — relabel-heavy данные сложнее). Сходится за ~26 минут на M3 Pro.

5. Гейт (пред-регистрация, НЕ двигать)

Тот же, что для v3: на той же held-out (530 реплик, untouched), после cascade-merge + ledger-filter:

Текущий v3-baseline (с фильтром): off-F1 0.476, type 0.339, hall 3. Чтобы v4 имела смысл, она должна не регрессировать + дать какое-то реальное улучшение (например, type-recall на каком-то классе).

6. Гипотезы

H+: v4 better calibrated → filter rejects FEWER cells (model agrees with filter rules already). Inference чище и быстрее. Type-macro может slightly расти.

H0: v4 ≈ v3 после фильтра. Гипотеза: фильтр сам по себе достаточный — переобучение под него ничего не добавляет.

H–: v4 over-abstains. Раз 35% позитивных меток переписаны в none, модель учится молчать слишком часто. Type-macro падает (особенно decision/fragment).

H– — реальный риск. Decision-recall на v3 уже низкий (~5%); если v4 убьёт его в ноль, type-macro макро-F1 упадёт.

7. Результат — H− confirmed

Прогнано 2026-05-26 (auto-сессия). cascade-v4 с v4@200 чекпойнтом против v3 (production):

| | off-F1 | type-macro | per-type (t/d/a/f) | hall | |---|---|---|---|---| | v3 cascade + filter (production) | 0.476 | 0.339 | 0.29/0.07/0.45/0 | 2/407 | | v4 self-distilled + filter | 0.455 | 0.174 ↓↓ | 0/0/0/0 | 2/407 |

Cascade-v4 ОТВЕРГНУТ. Type macro-F1 0.174 — провален гейт (>0.270 нужен). Все per-type F1 на board-классах = 0: HEAD-T v4 предсказывает none почти всегда. H− подтверждена.

8. Что это значит

Filter-as-label-corrector в его текущей форме (hard relabel) — слишком агрессивен. Когда 35% позитивных меток переписаны в none, модель учится не «когда применять правила фильтра» а «всегда абстиниться». В тренировке это даёт val_loss 0.055 (любая none-prediction корректна на 63% none-данных). На инференсе — model = filter = всегда none → доска пустая.

Урок: для перехода от model+filter к model-with-filter-baked-in нужна более мягкая supervision:

Это направление для v5+, не блокер: v3 production уже принят гейтом, cascade-v4 был добавочный эксперимент.

9. Архитектурное подтверждение

Важное: directed-сила сохранена by-construction — off-F1 0.455 у v4 точно равен baseline (HEAD-D неприкосновенен). Это архитектурное свойство каскада: что бы ни случилось с HEAD-T, directed-моат не страдает. Это и есть смысл «model proposes, ledger disposes» — независимые оси.


артефакты: cortex-lm/scripts/build_typeonly_v4.py · cortex-lm/v0/data_typeonly_v4_bal/ · cortex-lm/v0/adapters_headT_v4_selfdistill/ (не подключён) · cortex-lm/v0/eval_fb/cascade_v4_filtered.json

артефакты: cortex-lm/scripts/build_typeonly_v4.py · cortex-lm/v0/data_typeonly_v4_bal/ · cortex-lm/v0/adapters_headT_v4_selfdistill/