feat(ml): training hygiene — system-tagged images are absent from other concepts training
Step 2 of milestone #128. _hygiene_excluded_ids (training_data.py) is the one shared predicate: images carrying any system tag are dropped from every OTHER concepts head training — not positives (a rough wip tagged as a character drags the head toward generic-sketch) and not rejection or sampled negatives (a wip OF character X is not evidence against X). A system tags own head trains on them unfiltered; that is what makes auto-flagging banners work. Selection is split out of train_head as the sklearn-free head_training_ids so CI (no sklearn) can pin the behavior. CCIP: reference prototypes skip hygiene-tagged images — a faceless wip figure region must never become an identity reference — and the ref cache signature now counts hygiene applications, since tagging an image wip changes the reference set without touching character/region counts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CDgx8bQS5YrGRK76v8HUnM
This commit is contained in:
@@ -17,10 +17,33 @@ from typing import Any
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ...models import ImageRecord, TagSuggestionRejection
|
||||
from ...models import ImageRecord, Tag, TagSuggestionRejection
|
||||
from ...models.tag import image_tag
|
||||
|
||||
|
||||
def _hygiene_excluded_ids(session: Session) -> set[int]:
|
||||
"""Ids of images carrying ANY system tag (wip / banner / editor
|
||||
screenshot — milestone #128). These images are excluded from OTHER
|
||||
concepts' head training entirely: not positives (a rough wip tagged as a
|
||||
character drags that head toward 'generic sketch') and not sampled or
|
||||
rejection negatives (a wip OF character X is not evidence against X) —
|
||||
simply absent. A system tag's OWN head trains on them unchanged; that is
|
||||
what makes auto-flagging banners/editor screenshots work.
|
||||
|
||||
Item-level by design: a wip-tagged process video contributes (or
|
||||
withholds) ALL its sampled frames, though some may show the finished
|
||||
piece. Operator call 2026-07-03: with enough clean data this washes out —
|
||||
no per-frame handling.
|
||||
"""
|
||||
return set(
|
||||
session.execute(
|
||||
select(image_tag.c.image_record_id)
|
||||
.join(Tag, Tag.id == image_tag.c.tag_id)
|
||||
.where(Tag.is_system.is_(True))
|
||||
).scalars().all()
|
||||
)
|
||||
|
||||
|
||||
def _ids_with_tag(session: Session, tag_id: int) -> list[int]:
|
||||
return [
|
||||
r[0] for r in session.execute(
|
||||
|
||||
Reference in New Issue
Block a user