A Projekt III végén nem a modell, hanem az állítás az átadandó termék. A 39.3. Geometriai kontroll és metrika labor az utolsó geometriai és metrikai ellenőrzést végezte el; ez az egység azt a csomagot építi fel, amellyel egy másik személy a futtatás nélkül is meg tudja ítélni, hogy a riport egyes mondatai milyen feltételekkel igazak. Előismeret a 39.3. Geometriai kontroll és metrika metrika- és split-konvenciója, valamint a 38.4. Mentett modellből független inference betöltési egyezés fogalma. Induló kérdés: két kolléga ugyanazt a mentett predikciós fájlt kapja. Az egyik azt írja, hogy a corrupt teszten a jelenetenkénti páros különbségek mediánja , tehát a tipikus jelenet romlott; a másik azt, hogy a clean és a corrupt medián IoU különbsége , tehát javulás. Melyiküknek van igaza, és mit kellett volna a riportnak egyértelműen rögzítenie? A fejezet jelkonvenciója végig ugyanaz: , és pozitív romlást, negatív javulást jelent a corrupt oldalon.
A Projekt III főága a 39.1.–39.2. bináris szemantikus szegmentálása; ebben az
egységben ennek a kimenetéből készül a riport. A modell képenként egy
-es
logittérképet ad, a predikált maszk
(a küszöb a checkpoint része), és a doboz nem külön tanított kimenet,
hanem a predikált maszkból a 39.1. Feladat- és
annotációs döntés
leképezésével, a 39.3. Geometriai kontroll és
metrika bbox függvényével származtatott xyxy doboz;
üres predikált maszkra a szentinel
.
Legyen a tesztképek száma
,
indexeik
a teljes 360 képes tömbre nézve. Egy származtatott doboz
a ground-truth doboz
a metadata.csv azonos sémájú sora. Nemüres dobozra
és ugyanez
-ra;
a doboz területe
.
A fél-nyílt értelmezés miatt a metszet területe
az unió , és ; ha pontosan az egyik doboz a szentinel, az érték . A maszkon mért ettől különböző mennyiség, és a riport a kettőt mindig külön néven közli.
Definíció (prediction artifact). A prediction
artifact a modell egy rögzített, verziózott, géppel olvasható kimeneti
fájlja. A Projekt III-ban ez változatonként (clean, corrupt) egy
(60,1,24,24) alakú, uint8 maszktömb és egy
ilyen sémájú JSON:
{
"schema_version": "1.1",
"model_id": "glyphlab-seg-01",
"artifact_kind": "semantic_mask_predictions",
"split": "test",
"variant": "clean",
"threshold": 0.5,
"generated_at": "<ISO-8601 időpont, a szkript tölti ki>",
"mask_file": "artifacts/clean_masks.npy",
"bbox_convention": "xyxy, nullától indexelt, félig nyílt; üres maszk: [-1,-1,-1,-1]",
"predictions": [
{"index": 6, "scene_id": "G0-0003", "view_id": 0, "bbox": [14, 8, 16, 17], "fg_pixels": 18}
]
}Négy ellenőrzés tartozik hozzá: (i) az index lista
pontosan a metadata split=="test" sorainak globális indexe,
és a (scene_id, view_id) párok is ugyanabban a sorrendben
jönnek; (ii) minden bbox vagy a szentinel, vagy érvényes, a
rácson belüli, nemüres xyxy doboz; (iii) a maszktömb alakja
(60,1,24,24), értékei
;
(iv) minden fájl SHA-256 értéke szerepel a manifestben. A mintasor a
lenti futás clean artifactjának első sora; a fájlt az
export_delivery.py írja.
Definíció (model card). A model card a kiadott
modell dokumentuma; specifikációs része:
architektúraosztály és paraméterszám, input séma (NCHW, float32,
,
),
output séma, label/target szerződés, tanító split, a kiválasztás
szabálya (legjobb val loss), checkpoint hash, licenc és érvényességi
kör. Mitchell és társai [P30, 4. szakasz] eredeti javaslata szerint a
model card ennél több: a „Metrics”, „Evaluation Data” és „Quantitative
Analyses” szakaszok a kiadott checkpoint verziózott értékelési
összefoglalóját is tartalmazzák (metrikák, értékelési adat,
csoportonkénti és metszetenkénti eredmények). Ebben a projektben a
model_card.json evaluation mezője rögzíti az
értékelés adatát (teszt split, clean és corrupt), metrikáit és azt, hogy
a számértékek a manifestben lenyomatolt artifactokon futtatott
report_audit.py kimenetéből származnak; a számokat, a
futásonkénti naplókat, a per-kép táblázatokat és az ablációkat a riport
közli, mert az export a card megírásakor még nem futtatta az auditot. Ez
a szétválasztás helyi dokumentációs döntés, nem a model
card általános definíciója.
Definíció (limitations szakasz). A korlátok szakasz azokat a feltételeket sorolja fel, amelyek nélkül a riport állítása hamis lehet: szintetikus, egyobjektumos, zárt eloszlású adat; nincs üres input szerződés; a corrupt teszt egyetlen zajtípust takar; az IoU nem kalibráció; a képenkénti és scene-szintű metrika nem felcserélhető.
Definíció (source trace). A source trace az
állítástól a nyers bizonyítékig vezető lánc: adatgenerátor verziója és
seedje, metadata.csv és manifest.json hash-e,
tanító/evaluáló kód azonosítója, függőségi verziók, checkpoint hash,
betöltési egyezési jegyzőkönyv és a futtatási parancs. Ez nem
helyettesíti a mérést, hanem lehetővé teszi annak újrakeresését.
Definíció (report). A report az az emberi olvasásra szánt dokumentum, amely egy pontosan megfogalmazott állítást, annak feltételeit, a nyers metrikát és az értelmezési határt együtt közli. A Project III riportjának kötelező váza: kérdés; protokoll; model card hivatkozás; nyers táblázat; feltétel-ellenőrzési lista; nem futtatott kiterjesztések.
A levezetési kötelezettség egy választott eredményállítás teljes feltétel- és bizonyíték-ellenőrzése. Válasszuk a
R1 állítást: „A glyphlab-seg-01
checkpoint a corrupt teszteloszláson legalább
-tel
rosszabb mask_iou-t ad, mint a clean teszten, a következő
értelemben: a jelenetenkénti
különbségek mediánja legalább
.”
Pozitív
romlás, ezért R1 a
egyenlőtlenség.
Ez empirikus állítás, nem tétel. A felülvizsgálat azt kérdezi, hogy milyen feltételek mellett lenne a mondat a jelen adatokra értelmes. A feltételek:
models/seg_best.pt SHA-256 értéke a manifestben szerepel,
betöltése a 39.2. Encoder–decoder vagy lokalizációs
fej architektúrájával és a model card input-sémájával történt,
eval() módban. A 38.4. Mentett
modellből független inference
logit-egyezési küszöbe csak a CPU-float32 környezetben értelmezett; itt
a küszöbölt maszkkimenet egyezését a maszkfájl hash-e rögzíti.(scene_id, view_id) párt tartalmazza azonos
sorrendben. A corrupted_test.npy sorrendje a
metadata.csv test sorainak sorrendje; a predikciós artifact
index mezője ehhez a globális indexhez kötődik.mask_iou-jának átlagát vesszük,
és
;
a csoportosítás kulcsa kizárólag a scene_id, és minden
jelenethez pontosan a 0 és az 1 view tartozik, így 30 csoport van. A
hatás a páronkénti
értékek mediánja;
romlás.A bizonyíték típusa a 2. feltételre: metadata.csv test
sorainak indexe és a corrupted_test.npy hash-e; a 4.
feltételre: az evaluáló kód forrása és egy kézi három-scene kontroll; az
1. feltételre: manifest hash plusz betöltési jegyzőkönyv. Ha bármelyik
elem hiányzik, az R1 státusza „feltételes, ellenőrizetlen”, nem pedig
„igaz”.
A metrika-konvenció egy nem nyilvánvaló pontot rejt: a páronkénti különbségek mediánja nem azonos a két split mediánjának különbségével. Ezt a következő lemmában rögzítjük.
Lemma (páros medián-hatás és a mediánok különbsége). Legyenek és valós sorozatok, és legyen . Ekkor általában
Bizonyítás. Ellenpéldával: legyen és . Ekkor , rendezve , tehát . Ugyanakkor és , így a mediánok különbsége . A két mennyiség előjelben is eltér.
A lemma azt mondja ki, hogy a medián nem lineáris a páros kivonásra nézve; ez az 5.4. Függő képek, seedek és resampling alfejezetből ismert aggregálási óvatosság egy konkrét alakja. A riportnak ezért mindig a értékek mediánját kell közölnie, ha a párosított romlás a kérdés, és a táblázatban a két split mediánját külön oszlopban, a páronkénti statisztikákat pedig további oszlopban kell feltüntetnie. A lemma bizonyítása teljes, de nem bizonyítja R1 igazságát: R1-hez a mért értékek kellenek; ezeket a lenti labor futási jegyzőkönyve adja.
A fenti három scene tekinthető egy kiértékelési csonknak. Tegyük fel, hogy a per-scene IoU-k a lemma ellenpéldájának értékei:
| scene | |||
|---|---|---|---|
| S1 | 0,90 | 0,80 | |
| S2 | 0,50 | 0,60 | |
| S3 | 0,40 | 0,30 |
A páronkénti medián hatás : a rögzített konvenció szerint a tipikus scene a corrupt eloszláson romlott. Aki a clean medián () és a corrupt medián () különbségeként számol, értéket kap, és tévesen javulást jelentene. A per-image átlag egy harmadik érték: a clean átlag , a corrupt átlag , a különbség ; ez szintén nem a páros medián hatás. A példa tehát egyetlen nyers táblázatból három, egymással nem felcserélhető számot állít elő; a riportnak névvel és előjel-értelmezéssel kell ellátnia mindegyiket.
Az átadási csomagot a 39.2. Encoder–decoder vagy
lokalizációs fej főágának checkpointjából egy dokumentált generálási
lépés állítja elő, a lab/project3 munkakönyvtárban; a
csomag szerkezete:
lab/project3/delivery/
report.md
model_card.json
manifest.json
models/
seg_best.pt
artifacts/
clean_predictions.json
clean_masks.npy
corrupt_predictions.json
corrupt_masks.npy
src/
report_audit.py
n155_geom_control.py
Az export a checkpointban rögzített küszöbbel maszkot predikál a
clean és a corrupt tesztre, a maszkból a 39.3.
Geometriai kontroll és metrika bbox függvényével xyxy
dobozt származtat, és a manifestbe minden fájl SHA-256 értékét írja:
# lab/project3/export_delivery.py — n156: a főág (n154) checkpointjából a delivery/ csomag.
# Maszkpredikció küszöbbel, maszkból származtatott xyxy doboz (n155), hash-manifest, model card.
import datetime, hashlib, json, shutil
from pathlib import Path
import numpy as np
import pandas as pd
import torch
from n155_geom_control import bbox
from segmentation_head import DATA, SmallSegUNet
HERE = Path(__file__).resolve().parent
OUT = HERE / "delivery"
MODEL_ID = "glyphlab-seg-01"
def sha256(path):
return hashlib.sha256(Path(path).read_bytes()).hexdigest()
def main():
ckpt = torch.load(HERE / "checkpoints" / "seg_best.pt", map_location="cpu", weights_only=True)
model = SmallSegUNet()
model.load_state_dict(ckpt["model_state_dict"])
model.eval()
thr = float(ckpt["threshold"]) # sigmoid(z) > thr <=> z > logit(thr)
meta = pd.read_csv(DATA / "metadata.csv")
test = meta[meta["split"] == "test"] # a korrupt teszt sorrendje is ez
inputs = {"clean": np.load(DATA / "images.npy")[test["index"].to_numpy()],
"corrupt": np.load(DATA / "corrupted_test.npy")}
for d in ("artifacts", "models", "src"):
(OUT / d).mkdir(parents=True, exist_ok=True)
shutil.copyfile(HERE / "checkpoints" / "seg_best.pt", OUT / "models" / "seg_best.pt")
files = {"checkpoint": "models/seg_best.pt"}
for name, x in inputs.items():
with torch.no_grad():
prob = torch.sigmoid(model(torch.from_numpy(x.astype(np.float32)))).numpy()
pred = (prob > thr).astype(np.uint8) # (60,1,24,24)
np.save(OUT / "artifacts" / f"{name}_masks.npy", pred)
art = {
"schema_version": "1.1", "model_id": MODEL_ID,
"artifact_kind": "semantic_mask_predictions", "split": "test",
"variant": name, "threshold": thr,
"generated_at": datetime.datetime.now(datetime.timezone.utc).isoformat(timespec="seconds"),
"mask_file": f"artifacts/{name}_masks.npy",
"bbox_convention": "xyxy, nullától indexelt, félig nyílt; üres maszk: [-1,-1,-1,-1]",
"predictions": [
{"index": int(r.index), "scene_id": r.scene_id, "view_id": int(r.view_id),
"bbox": list(bbox(pred[j])), "fg_pixels": int(pred[j].sum())}
for j, r in enumerate(test.itertuples())],
}
(OUT / "artifacts" / f"{name}_predictions.json").write_text(json.dumps(art, indent=1))
files[name] = f"artifacts/{name}_predictions.json"
files[f"{name}_masks"] = art["mask_file"]
manifest = {"files": {k: {"path": v, "sha256": sha256(OUT / v)} for k, v in files.items()},
"inputs": {n: sha256(DATA / n) for n in
("images.npy", "corrupted_test.npy", "masks.npy", "metadata.csv")}}
(OUT / "manifest.json").write_text(json.dumps(manifest, indent=2))
card = {"model_id": MODEL_ID, "architecture": "SmallSegUNet (lab/project3/segmentation_head.py)",
"params": ckpt["params"], "input_schema": "float32 NCHW (N,1,24,24), [0,1]",
"output_schema": "logit (N,1,24,24); maszk = sigmoid > threshold",
"threshold": thr, "derived_bbox": "maszk legkisebb befoglaló xyxy doboza (n155 bbox)",
"selection_rule": "legkisebb val BCE epoch (train_seg.py)",
"checkpoint_sha256": manifest["files"]["checkpoint"]["sha256"],
"validity_scope": "GlyphLab 1.0 szintetikus, egyobjektumos képek",
"evaluation": {"data": "teszt split (metadata.csv), clean: images.npy, corrupt: corrupted_test.npy",
"metrics": "mask_iou, bbox_iou (n155), képenkénti és jelenetszintű összesítés",
"results": "report_audit.py kimenete a manifest artifactjain (lásd riport)"}}
(OUT / "model_card.json").write_text(json.dumps(card, indent=2, ensure_ascii=False))
for src in ("n155_geom_control.py", "report_audit.py"):
shutil.copyfile(HERE / src, OUT / "src" / src)
print(f"delivery kész: {len(test)} teszt-kép, küszöb {thr}, checkpoint epoch {ckpt['epoch']}")
if __name__ == "__main__":
main()A report_audit.py feladata a fenti feltétel-ellenőrzési
lista gépi része. A doboz-geometriát nem írja újra, hanem a csomagba
másolt n155_geom_control.py modulból importálja, így a
xyxy-sorrend és a validátor egyetlen forrásból jön. A jelenetszintű
csoportosítás kulcsa csak a scene_id; a beépített
selftest két jelenetes fixture-rel ellenőrzi, hogy a
képenkénti és a jelenetenkénti medián valóban eltérhet.
#!/usr/bin/env python3
# lab/project3/report_audit.py
"""Projekt III riport-audit: artifact-séma, hash, párosítás, maszk- és bbox-IoU (NumPy + stdlib).
Jelkonvenció: D_s = I_s(clean) - I_s(corrupt); pozitív D_s romlás a corrupt oldalon,
negatív D_s javulás."""
import argparse, csv, hashlib, json, statistics, sys
from pathlib import Path
import numpy as np
sys.path.insert(0, str(Path(__file__).resolve().parent))
from n155_geom_control import Box, box_iou, validate_box
def sha256(path):
return hashlib.sha256(Path(path).read_bytes()).hexdigest()
def mask_iou(p, t):
p, t = p.astype(bool), t.astype(bool)
union = np.logical_or(p, t).sum()
return float(np.logical_and(p, t).sum() / union) if union else 1.0
def per_scene(values, rows):
"""Kulcs csak a scene_id; minden jelenethez pontosan a 0 és 1 view tartozik."""
groups = {}
for v, r in zip(values, rows):
groups.setdefault(r["scene_id"], {})[int(r["view_id"])] = v
for s, views in groups.items():
assert set(views) == {0, 1}, f"{s}: a view-k {sorted(views)}"
return {s: statistics.mean(views.values()) for s, views in groups.items()}
def selftest():
# Két jelenet, eltérő view-különbségekkel: a képenkénti és a jelenetenkénti medián eltér.
rows = [{"scene_id": "a", "view_id": 0}, {"scene_id": "a", "view_id": 1},
{"scene_id": "b", "view_id": 0}, {"scene_id": "b", "view_id": 1}]
d = [0.4, 0.0, 0.1, 0.1]
ds = per_scene(d, rows)
assert len(ds) == 2 and ds == {"a": 0.2, "b": 0.1}
assert statistics.median(d) == 0.1 and abs(statistics.median(ds.values()) - 0.15) < 1e-12
print("selftest OK")
def main():
p = argparse.ArgumentParser()
p.add_argument("--clean", required=True)
p.add_argument("--corrupt", required=True)
p.add_argument("--data", required=True, help="a GlyphLab data/ könyvtára")
p.add_argument("--manifest", required=True)
args = p.parse_args()
selftest()
root = Path(args.manifest).resolve().parent
man = json.loads(Path(args.manifest).read_text())
for key, f in man["files"].items(): # hash-lánc
assert sha256(root / f["path"]) == f["sha256"], key
meta = list(csv.DictReader(open(Path(args.data) / "metadata.csv", newline="")))
test = [r for r in meta if r["split"] == "test"]
assert len(test) == 60 and len({r["scene_id"] for r in test}) == 30
gt_masks = np.load(Path(args.data) / "masks.npy")
res = {}
for name, path in (("clean", args.clean), ("corrupt", args.corrupt)):
art = json.loads(Path(path).read_text())
preds = art["predictions"]
assert [int(q["index"]) for q in preds] == [int(r["index"]) for r in test]
assert [(q["scene_id"], q["view_id"]) for q in preds] == \
[(r["scene_id"], int(r["view_id"])) for r in test] # azonos képkészlet és sorrend
masks = np.load(root / art["mask_file"])
assert masks.shape == (60, 1, 24, 24) and set(np.unique(masks)) <= {0, 1}
m_iou = [mask_iou(masks[j], gt_masks[int(r["index"])]) for j, r in enumerate(test)]
b_iou = [box_iou(validate_box(Box(*q["bbox"])),
Box(*(int(r[k]) for k in ("xmin", "ymin", "xmax", "ymax"))))
for q, r in zip(preds, test)]
res[name] = {"mask_iou": per_scene(m_iou, test), "bbox_iou": per_scene(b_iou, test)}
summary = {"sign_convention": "D_s = clean - corrupt; D_s > 0 romlás", "n_scenes": 30}
for metric in ("mask_iou", "bbox_iou"):
c, x = res["clean"][metric], res["corrupt"][metric]
assert set(c) == set(x) and len(c) == 30
D = [c[s] - x[s] for s in sorted(c)]
summary[metric] = {
"clean_scene_median": round(statistics.median(c.values()), 6),
"corrupt_scene_median": round(statistics.median(x.values()), 6),
"paired_median_D": round(statistics.median(D), 6),
"mean_D": round(statistics.mean(D), 6)}
print(json.dumps(summary, ensure_ascii=False, indent=2))
if __name__ == "__main__":
main()Az ellenőrzés nem bizonyítja a modell minőségét; azt bizonyítja, hogy
az artifact sémája, a hash-lánc, a párosítás és a jelenetszintű
aggregáció helyes, és hogy a mask_iou és a
bbox_iou külön, azonos előjelkonvencióval kerül a
riportba.
A teljes Projekt III-út a lab/project3 könyvtárból:
cd lab/project3
python annotation_spec.py --data ../data # n153: célszerződés
python train_seg.py # n154: főág, checkpoints/seg_best.pt
python n155_geom_control.py # n155: geometriai kontroll
python export_delivery.py # n156: delivery/ csomag
cd delivery
python src/report_audit.py \
--clean artifacts/clean_predictions.json \
--corrupt artifacts/corrupt_predictions.json \
--data ../../data --manifest manifest.jsonFutási jegyzőkönyv (eredeti GlyphLab-adat, CPU, Python 3.12.3, NumPy 2.3.5, PyTorch 2.14.1+cpu; a tanítás és az export két futása azonos checkpoint- és maszkfájl-hasht adott; a JSON-artifactok hash-e az időbélyeg miatt futásonként más). Az audit kimenete:
{
"sign_convention": "D_s = clean - corrupt; D_s > 0 romlás",
"n_scenes": 30,
"mask_iou": {"clean_scene_median": 1.0, "corrupt_scene_median": 0.7,
"paired_median_D": 0.297129, "mean_D": 0.321315},
"bbox_iou": {"clean_scene_median": 1.0, "corrupt_scene_median": 0.136209,
"paired_median_D": 0.839373, "mean_D": 0.745821}
}Az átadandó report.md minimális szerkezete, a fenti
futás értékeivel:
# Alkalmazási riport: GlyphLab szegmentálás (glyphlab-seg-01)
## Állítás
R1: a jelenetenkénti D_s = mask_iou(clean) − mask_iou(corrupt) mediánja ≥ 0,05
(pozitív D_s romlás a corrupt oldalon).
## Feltétel-ellenőrzés
| Feltétel | Bizonyíték | Státusz |
|---|---|---|
| checkpoint hash | manifest.json > files.checkpoint.sha256 | ellenőrzött |
| párosítás | metadata test sorrend + artifact index, scene_id, view_id | ellenőrzött |
| modellválasztás | checkpoints/seg_train_log.json, legkisebb val BCE | ellenőrzött |
| metrika | report_audit.py selftest + kézi 3-scene kontroll | ellenőrzött |
| adathatár | GlyphLab 1.0, szintetikus | korlát |
## Nyers eredmény
| mennyiség | mask_iou | bbox_iou |
|---|---|---|
| clean per-scene medián | 1,000 | 1,000 |
| corrupt per-scene medián | 0,700 | 0,136 |
| páros medián D_s (clean − corrupt) | +0,297 | +0,839 |
| scene-ek száma | 30 | 30 |
## Értelmezés
R1 ezen a futáson teljesül: med(D) = 0,297 ≥ 0,05, tehát romlás.
A származtatott doboz sokkal érzékenyebb: néhány hamis előtérpixel is
a kép széléig nyújtja a befoglaló téglalapot.
## Nem futtatott kiterjesztés
A valós ipari/orvosi validáció terv, nem eredmény.Értelmezés. A clean teszten mindkét medián
:
a szintetikus, egyobjektumos képeken a szegmentálás a tipikus jelenetben
hibátlan. A korrupt teszten a mask_iou mediánja
-re,
a bbox_iou-é
-re
esik; a páros mediánok
és
,
mindkettő romlás. A két metrika eltérése nem ellentmondás: a maszk-IoU
néhány hamis előtérpixelt arányosan büntet, a maszkból származtatott
befoglaló doboz viszont egyetlen távoli hamis pixeltől is a kép széléig
nyúlhat. Ezért nevezzük a két mennyiséget külön, és ezért nem szabad a
dobozmetrikát a maszkmetrika helyett jelenteni. Más könyvtárverzióval
vagy más CPU-n az utolsó jegyek eltérhetnek; a saját audit-kimenetet és
a manifest hash-eit kell archiválni.
F1 (fogalmi, nehézség 1). Egy hallgató a model cardba beírja a legutóbbi clean teszt accuracy értékét, a riportba pedig a betöltési Python parancs teljes implementációját. Azonosítsa, melyik dokumentum melyik információnak a helye, és adjon példát arra, milyen hiba keletkezik, ha a kettő felcserélődik.
F2 (levezetési, nehézség 2). Igazolja a lemma állítását az , sorozatokra, és adja meg mind a páronkénti medián hatást, mind a mediánok különbségét. Ellenőrizze, hogy itt is előjelváltás történik-e.
F3 (implementációs, nehézség 2). Írjon
invalid_bbox_finder.py nevű függvényt, amely egy
predictions JSON-listát kap, és visszaadja azon indexek
listáját, ahol a doboz kilép a
tartományból, vagy nem teljesül
,
.
A megoldásnak tartalmazzon egy három elemből álló, egy hibás dobozt
tartalmazó tesztinputot.
F4 (hibakeresési, nehézség 2). A következő riportkód
a corrupt párosítást a DataFrame újraindexelése után végzi
el:
clean_test = meta[meta.split == "test"].reset_index(drop=True)
corrupt_preds = pd.read_json("corrupt_predictions.json")
corrupt_preds = corrupt_preds.sort_values("index").reset_index(drop=True)
D = clean_test["iou_clean"] - corrupt_preds["iou_corrupt"]Mi a hiba oka, mi a következménye a páros medián hatásra, és hogyan javítható úgy, hogy a javítás ellenőrizhető legyen?
F5 (kísérleti/transzfer, nehézség 3). Egy mérnök a GlyphLab szegmentáló modellt és a belőle származtatott dobozokat ipari alkatrészek dobozolására szeretné használni. Tervezzen érvényességi határelemzést: mi a megfigyelési egység, milyen baseline, metrika és annotációs forrás kell, és mely következtetések nem vonhatók le a szintetikus eredményből? A terv lehet nyitott, de minden elemnél adja meg az alternatíva indokát.
F1. A kiadott checkpoint clean test accuracy-je a model card értékelési összefoglalójába tartozhat [P30, 4. szakasz], de csak a checkpoint hash-ével, a teszt split azonosítójával és az értékelő kód verziójával együtt; a „legutóbbi” futás értéke, hivatkozás nélkül, nem. A betöltési kód teljes implementációja egyik dokumentumba sem való: a verziózott forráskódban van, a model card az architektúraosztályt, az input sémát és a checkpoint hash-ét rögzíti, a riport pedig a kódverzióra hivatkozik. Hibás esetben a model card egy másik checkpoint vagy split mérését hordozza, mintha az a kiadott modellé lenne; a riport pedig újraimplementálja a betöltést ahelyett, hogy a verziózott kódra hivatkozna, így a source trace megszakad.
F2. , rendezve , tehát a páronkénti medián . A mediánok: , , különbség . Itt nem előjelváltás, hanem előjelütközés van: a páronkénti hatás pozitív, a mediánok különbsége negatív. A példa újra megerősíti, hogy a két aggregáció nem felcserélhető.
F3. Egy lehetséges megoldás:
def invalid_bboxes(predictions):
out = []
for pr in predictions:
x1, y1, x2, y2 = (float(v) for v in pr["bbox"])
if not (0.0 <= x1 and x2 <= 24.0 and x1 < x2):
out.append(pr["index"])
continue
if not (0.0 <= y1 and y2 <= 24.0 and y1 < y2):
out.append(pr["index"])
return out
sample = [
{"index": 10, "bbox": [1.0, 2.0, 20.0, 22.0]},
{"index": 11, "bbox": [23.0, 1.0, 26.0, 8.0]},
{"index": 12, "bbox": [4.0, 9.0, 4.0, 15.0]},
]
print(invalid_bboxes(sample)) # [11, 12]A 11. doboz kilép a tartományból, a 12. dobozra , tehát nulla szélességű, ami a félig nyílt szerződés szerint érvénytelen. Alakellenőrzés: a bemenet hossza 3, a kimenet hossza 2, a kimenet elemei a bemeneti indexek közül valók.
F4. A hiba oka: a
reset_index(drop=True) a rendezés után új, 0-tól induló
sorszámmal párosítja a két táblát, de a corrupt predikciókat a
sort_values("index") a globális index szerint rendezi,
miközben a clean oldal a metadata sorrendjét őrzi. Ha a két sorrend
bármely okból eltér, a scene–view párok felcserélődnek. Következmény: a
értékek hamis párokból készülnek, a páronkénti medián hatás torzul, és a
riport akár előjelhibás következtetést is közölhet. Javítás: a két
táblát a globális index mezőn kell összekapcsolni, például
pd.merge(..., on="index", how="outer"), majd ellenőrizni,
hogy a (scene_id, view_id) párok oszloponként azonosak; ha
nem, a programnak hibát kell dobnia.
F5. Egy lehetséges terv. Megfigyelési egység: ipari alkatrész-sorozat, mert az egy gyártási sorozaton belüli képek függők. A GlyphLab scene_id-jének szerepét a sorozatazonosító veszi át. Adat: saját, licencelt képek maszkkal vagy dobozzal; az annotációt két független annotátor közötti egyezéssel kell kontrollálni. Split: sorozatszinten train/val/test, az osztály- vagy pozícióeloszlás rétegzésével. Baseline: fix középpontú vagy a kép szélénél található legnagyobb intenzitású doboz; a 39.3. Geometriai kontroll és metrika alfejezetben bemutatottakhoz hasonlóan ez a szintetikus eloszláson erős lehet. Metrika: per-sorozat átlag IoU, páros clean–corrupt vagy éles–homályos összehasonlítás, üres inputra vonatkozó külön szabály. Ami nem következik a GlyphLab eredményből: az ipari pontosság semmilyen konkrét értéke, a ritka hibák gyakorisága, a fényviszony- vagy anyagváltás alatti viselkedés, és a biztonsági alkalmazhatóság. A szintetikus modell legfeljebb kiinduló implementációs ellenőrzés; az ipari átvitelhez új mérés és emberi felülvizsgálati protokoll kell.
A leggyakoribb hiba az, hogy a szintetikus lokalizáció pontosságát orvosi vagy ipari validációként olvassák. A GlyphLab teszt minden képe pontosan egy, a generátor által garantáltan jelen lévő alakzatot tartalmaz; ezért a modell nem tanulja meg az „objektum nélküli kép” esetet, és nagy valószínűséggel üres vagy idegen textúrájú bemenetre is egy magabiztos dobozt ad. Konkrét ellenpélda a keretből: egy 24×24, -beli, de előtér nélküli inputon az IoU-ellenőrzés nem is értelmezhető, mert a ground-truth doboz hiányzik; aki ilyenkor az artifactban szereplő dobozt használná, az IoU-t 0-val vagy kihagyással számolná, miközben a riport R1 állítása ezt a tartományt nem fedi le. Az állítás tehát csak a rögzített szintetikus eloszlásra vonatkozik; a valós bevetéshez az üres-input szerződést külön kell definiálni.
Ellenőrző kérdések: (1) A fenti kézi példában a páronkénti medián (romlás), a mediánok különbsége ; ez a lemma ellenőrzése, és mutatja, miért kell az előjel-konvenciót a riportban kimondani. (2) A prediction artifact nem a riport, mert az artifact gépi, verziózott, a riport emberi értelmezést és korlátokat is tartalmaz. (3) A forráslánc megszakad, ha a checkpoint hash nincs a manifestben, vagy ha a corrupt párosítást globális index helyett új sorszámmal végzik. Visszahívás: a 38.4. Mentett modellből független inference betöltési egyezés két szintje, a hash és a numerikus tolerancia; a 35.4. Korlátok, eredet és döntési felelősség adathatár, amely szerint a clean accuracy nem shift alatti garancia; a 27.4. Instance mask és összetett feladat instance-annotáció, amelyre azért nincs itt szükség, mert az alapváltozat egy objektumra lokalizál, így a szemantikus és instance szétválasztás nem terheli az artifact sémáját.
A Projekt III átadása négy, egymástól elkülönülő komponensből áll: a verziózott prediction artifact, a kiadott checkpointhoz rögzített model card, a korlátokat rögzítő limitations szakasz és a feltételeket a nyers méréssel összekötő jelentés. A source trace minden állítást hash-elt inputhoz, kódhoz és checkpoint-hoz köt. A páros clean–corrupt hatást a scene-szintű különbségek mediánjával kell jelenteni, mert a mediánok különbsége ellenpéldánkban előjelet váltott. A riport mérési mezőit a dokumentált főág (tanítás, export, audit) tényleges futása tölti ki; a hallgatói labornak a saját futását a manifest hash-eivel együtt kell archiválnia. A konvenció végig , pozitív érték romlás. A szintetikus szegmentálás sem orvosi, sem ipari validációt nem helyettesít.
A 40.1. Összetett levezetési vizsga összetett levezetési vizsgán a jelentés állításait úgy kell majd újra elemezni, hogy a forráslánc egy pontjának megszakadása mellett is helyesen azonosítsa a hallgató, mely következtetés marad feltételes és melyik válik hamissá.