Ez az egység az adatfolyam legelső, a tenzorműveletek előtti szerződését tárgyalja: honnan jön a megfigyelés, milyen jogosultsággal használjuk, mi a független megfigyelési egység, és az annotáció mely rekordhoz tartozik. Az 5.4. Függő képek, seedek és resampling már megmutatta, hogy a GlyphLab 360 képéhez 180 jelenet tartozik, ezért a képszám és a független egységek száma eltér. A 11.4. Egy teljes PyTorch tanítási iteráció a PyTorch adatbetöltést a split után építette fel; most a splitet megelőző, ellenőrizhető réteget rögzítjük. A 8.4. II. ellenőrző pont: korrekt tanulási állítás korrekt tanulási állításához, a 21.4. Osztályarány, súlyozás és céleloszlás céleloszlásához és a 20.4. V. ellenőrző pont: indokolt CNN-választás adatfeltételes architektúradöntéséhez is ugyanaz a követelmény: az adathivatkozásnak egyértelműnek kell lennie a kísérlet teljes élettartama alatt.
Induló kérdés. A GlyphLab train halmaza 240 képet tartalmaz. Hány független statisztikai egység van ebben a halmazban: 240 vagy 120? Miért befolyásolja a válasz a validációs hibát? A becslését a 3. szakasz lemma és az 5. szakasz auditja után ellenőrizheti.
A tárgyalt fogalmakat rekordok és leképezések nyelvén adjuk meg, mert a későbbi ellenőrzés ezeket a tulajdonságokat kódban is vizsgálja.
Adateredet (provenance). Egy
példányból álló adathalmaz provenance-rekordja egy rendezett
lista, amely legalább az alábbiakat tartalmazza: a generáló vagy gyűjtő
folyamat azonosítója és verziója; a forrásra mutató azonosító; a
példányok és a csoportok generálásának paraméterei, köztük a véletlen
mag (seed); valamint a nyers állapotból a szállított állapotba vivő
transzformációk leírása. A GlyphLab esetében a generátor az
generate_data.py --output data parancs, a verzió 1.0, a
seed 20261020, a nyers szintetikus jelenetet a két zajos nézet követi. A
provenance-rekord tehát nem a modell hibájának minőségi leírása, hanem a
reprodukálhatóság szerződése.
Licenc. A licenc a felhasználási jogosultság jognyilatkozata egy meghatározott adatváltozatra. Megkülönböztetjük az adathalmaz nevét, az adatváltozat lenyomatát és a licencfeltételeket. A GlyphLab saját, oktatási célra előállított adata a könyv laborjának szerződése alá esik; a manifest verziója és SHA-256 lenyomatai azonosítják a változatot. Egy adathalmaz publikus elérhetősége nem jogi kategória, ezért a licencet konkrét URL-hez, verzióhoz és terjesztőhöz kötjük.
Duplikátum. Legyen
két példány, és
egy hashfüggvény a bájtábrázoláson. Azt mondjuk, hogy
és
tartalom-duplikátum, ha
és
.
A tartalom-duplikátum nem azonos a függő párral: a GlyphLab két
view-ja azonos jelenetből származik, ezért statisztikailag függő, de a
view-nként független zaj miatt a bájtábrázolásuk általában különbözik.
Azt, hogy egy duplikátum rekord-duplikátum-e, a deduplikációs
kulcs dönti el: a GlyphLab kulcsa az
(index, scene_id, view_id) hármas, amely garantáltan
egyedi, még akkor is, ha két view pixelszinten megegyezne.
Csoport (scene/patient/device group). Legyen
a példányindexek halmaza,
a csoportazonosítók halmaza, és
a csoporthozzárendelés. A GlyphLabben
a metadata.csv scene_id oszlopa, az
példányhoz
csoport. Minden
-re
a
halmaz elemei azonos független forrásból származnak; a köztük lévő
korreláció miatt a statisztikai egység a csoport, nem a kép. Orvosi
adatokban
jellemzően betegazonosító, többkamerás felvételeknél eszköz- vagy
felvételazonosító.
Annotáció és címke-hivatkozás. Legyen
az osztályok száma,
a címke. A GlyphLabben
,
a label oszlop int64 értéke. Az annotációs rekordok halmaza
;
minden
sor egy
példányra hivatkozik. A címke-hivatkozás egyedisége azt
jelenti, hogy
injektív: két különböző annotációs sor nem hivatkozhat ugyanarra a
példányra. A GlyphLabben
,
és
bijekció, mert a metadata.csv index oszlopa az
egész
halmaz permutációja. Az annotáció a GlyphLabben a címkén túl a maszkot
és a fél-nyílt, nullától indexelt xyxy dobozt is tartalmazza:
xmin≤x<xmax, ymin≤y<ymax, a doboz
területe
.
Ebben a szakaszban a megírandó egység bizonyítási kötelezettségét teljesítjük: megadjuk a csoportszintű diszjunkt felosztás reprezentációs invariánsát, és belátjuk a címke-hivatkozás egyediségének sorrend-invarianciáját.
Lemma (a csoportos split reprezentációja). Legyen és véges halmaz, és . Ha minden esetén
akkor létezik pontosan egy úgy, hogy
Bizonyítás. Szűkítsük -t az értékkészletére, így feltehető, hogy szürjektív. Minden -hez válasszunk egy elemet, amelyre , és definiáljuk -t. Meg kell mutatnunk, hogy ez a definíció független a reprezentáns választásától. Ha egy másik választás, akkor ; az (1) feltétel szerint ezért . Tehát jól definiált. Továbbá minden -re
mert -t a csoport egy reprezentánsaként definiáltuk, és az előbb belátott jól definiáltság miatt a csoport bármely reprezentánsa ugyanazt a -értéket adja, speciálisan maga is. Ez éppen (2). Ha is eleget tesz (2)-nek, akkor minden -re , tehát a függvény egyértelmű.
A lemma következménye a diszjunkt felosztás invariánsa: a split nem a képek, hanem a csoportok partícióján értelmezett. Mivel a -ősképek diszjunkt uniója, az (1) tulajdonság pontosan azt mondja ki, hogy minden split halmaz teljes csoportok uniója. Ha a felosztás egyszer teljesíti (1)-et, akkor a rekordok tetszőleges permutációja után is teljesíti, mert a feltétel csak a értékpárokon múlik, nem a sorrenden. A GlyphLabben tehát a 120 train jelenet mindkét view-ja a trainbe, a 30 val jelenet mindkét view-ja a valba, a 30 test jelenet mindkét view-ja a testbe kerül; a képszám 240, de a független egységek száma 120. Ez válaszol az induló kérdésre.
Állítás (a címke-hivatkozás egyediségének sorrend-invarianciája). Legyen , és legyen a metadata-rekordok halmaza , ahol a rekord sorszáma nem feltétlenül azonos a hivatkozott indexszel. Ha a hivatkozások páronként különbözőek, akkor a rekordok tetszőleges permutációja után is injektív marad a hivatkozás, és minden példányhoz legfeljebb egy rekord tartozik.
Bizonyítás. Egy permutáció a rekordok halmazának átrendezése, nem a hivatkozásoké. Az új hivatkozásfüggvény , tehát értékkészlete azonos az eredeti értékkészletével. Mivel injektív, az értékkészletben nincs ismétlés, így is injektív. Ha és az eredeti hivatkozások éppen -t fedik le, a permutált változat is bijekció, vagyis minden példányhoz pontosan egy címke-, maszk- és dobozrekord tartozik.
A GlyphLab audit tehát két invariánst ellenőriz: a csoportos split
(1) tulajdonságát, valamint azt, hogy a metadata.index a
halmaz permutációja. A SHA-256 a fájltartalom változatlanságát rögzíti,
és így a provenance három rétegét — folyamat, csoport, lenyomat — együtt
zárja.
Tekintsünk hat képet három jelenetből, jelenetenként két view-val. Az alábbi CSV-sorok a GlyphLab sémáját követik:
index,scene_id,view_id,label,split,xmin,ymin,xmax,ymax
0,S00,v0,0,train,2,3,21,20
1,S00,v1,0,train,3,2,20,21
2,S01,v0,1,train,0,6,24,18
3,S01,v1,1,train,1,6,23,18
4,S02,v0,2,val,5,5,19,9
5,S02,v1,2,val,4,5,20,9
Az (1) tulajdonság ellenőrzése: a S00 csoport mindkét
elemének splitje train, a S01 csoporté szintén
train, a S02 csoporté val.
Létezik tehát
,
,
és a lemma szerint a split a csoportokon értelmezett. Ha a 4. indexű
S02,v0 rekordot a val helyett
train-re írnánk át, akkor az (1) feltétel sérülne, mert az
5. indexű S02,v1 rekord val maradna; a 3.
szakasz lemma miatt nem létezne olyan
,
amelyre
.
A címke-hivatkozás szempontjából a hat index érték egy
permutáció, tehát minden képtömbbeli pozícióhoz pontosan egy annotációs
sor tartozik. A két view nem tartalom-duplikátum: a pixeltenzoraik a
view-specifikus zaj miatt különböznek, rekordszinten pedig a
view_id is eltér. Ez a hat soros példa a labor teljes, 360
soros ellenőrzésének kicsinyített, kézzel követhető előképe.
Az átadandó eredmény egy futtatható audit, amely a lab könyvtár
data/manifest.json és data/metadata.csv
fájljait ellenőrzi. Input: a rögzített GlyphLab adat az [ADATOK.md]
szerződése szerint. A példában nincs véletlen, tenzortanulás, GPU vagy
dtype-választás: CPU-s fájlműveletek, seed=None,
dtype nem értelmezett. Futtatási könyvtár
lab/, parancs:
python audit_manifest.py --data dataA megírandó kód:
import argparse, hashlib, json, sys
from pathlib import Path
import numpy as np
import pandas as pd
# Input: GlyphLab data könyvtár; CPU fájlművelet, nincs véletlen.
def sha256_of(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def check(data_dir: str) -> list[str]:
data = Path(data_dir)
errors: list[str] = []
manifest = json.loads((data / "manifest.json").read_text())
# feltételezett séma: version, seed, shapes, splits, files{path:sha256}
for key in ["version", "seed", "shapes", "splits", "files"]:
if key not in manifest:
errors.append(f"hianyzik manifest kulcs: {key}")
for rel, sha in manifest.get("files", {}).items():
p = data / rel
if not p.exists():
errors.append(f"hianyzik adatfajl: {rel}")
elif sha != sha256_of(p):
errors.append(f"sha256 hibas: {rel}")
meta = pd.read_csv(data / "metadata.csv")
n = len(meta)
# index: 0..N-1 permutacio (cimkehivatkozas egyedisege)
if set(meta["index"]) != set(range(n)) or meta["index"].duplicated().any():
errors.append("index nem egyedi 0..N-1 permutacio")
if not meta["label"].isin({0, 1, 2}).all():
errors.append("label {0,1,2}-n kivuli ertek")
# csoportos split: scene -> split egyertelmu
bad = meta.groupby("scene_id")["split"].nunique()
bad = bad[bad != 1]
if not bad.empty:
errors.append(f"csoportos split sertve: {list(bad.index)}")
# megfigyelt darabszamok a manifesttel szemben
counts = meta["split"].value_counts().to_dict()
if counts != manifest.get("splits"):
errors.append(f"split-szam elteres: {counts}")
# doboz: fél-nyílt xyxy, 0<=min<max<=24, pozitív terület
box_ok = (
meta["xmin"].between(0, 24)
& meta["ymin"].between(0, 24)
& meta["xmax"].between(0, 24)
& meta["ymax"].between(0, 24)
& (meta["xmin"] < meta["xmax"])
& (meta["ymin"] < meta["ymax"])
)
if not box_ok.all():
errors.append("hibas doboz, nem fél-nyílt xyxy")
return errors
if __name__ == "__main__":
ap = argparse.ArgumentParser()
ap.add_argument("--data", default="data")
args = ap.parse_args()
errs = check(args.data)
for e in errs:
print("HIBA:", e)
if errs:
sys.exit(1)
print("OK: minden GlyphLab audit-ellenorzes atment")Az alábbi kimenet a kódból várt, ellenőrzött állapotot mutatja; a tényleges futási jegyzőkönyvet a laborban kell rögzíteni:
OK: minden GlyphLab audit-ellenorzes atment
Ha a manifest JSON-kulcssémája a tényleges fájlban eltér a kódban
feltételezett files/splits szerkezettől, az
audit első feladata a séma feloldása; a hibajelzés ekkor pontosan
megnevezi a hiányzó kulcsot.
A feladat második fele egy terv, nem egy elvégzett letöltés. A következő sablont bármely választott külső adatra kitöltheti:
Választható minta: ha a hallgató a CIFAR-10 nevű adatkészletet választja, a protokoll 2. és 3. pontjába a ténylegesen beszerzett tükör URL-jét, SHA-256-ját és licencnyilatkozatát kell beírni. A jelen kézirat nem állítja, hogy a CIFAR-10-et letöltöttük vagy licencét ellenőriztük; a „CIFAR-10 publikus” kijelentés önmagában nem protokoll.
A leggyakoribb hiba így hangzik: „Az X adathalmaz publikus, tehát
a felhasználásom jogszerű, és a neve azonosítja az adatokat.” A két
állítás egyike sem következik a névből. Legyen
és
két archívum, mindkettő GlyphAlike-v1.zip néven terjesztve;
SHA-256 lenyomata
,
licencfeltétele CC BY 4.0,
lenyomata
,
feltétele pedig „csak nem kereskedelmi kutatásra”. A „GlyphAlike
szabadon használható” mondat
-re
igaz lehet, de
-re
hamis, pedig a név azonos. A hibás érvelés következménye kettős: a
kísérlet nem reprodukálható, mert a lenyomat nélkül nem tudjuk, melyik
változatot használtuk, és a jogi feltétel megszegése a publikált
eredményt is terheli. A javítás a 2. szakasz hármasának rögzítése: név,
lenyomat, licencfeltétel együtt, konkrét URL-lel és hozzáférési
dátummal.
F1 (fogalmi, nehézség 1). Magyarázza el a különbséget a tartalom-duplikátum és a függő nézetpár között a GlyphLabben. Adjon olyan kis ellenpéldát, amelyben két kép azonos címkéjű és azonos pixelsorú, mégsem kezelhető ugyanannak a rekordnak a csoportazonosító miatt. Várt átadandó eredmény: definíciók és a 4. szakasz sémájában megadott ellenpélda.
F2 (levezetési, nehézség 2). Adott , , , . Legyen , , . Mutassa meg, hogy nem létezik , amelyre , és azonosítsa a lemma (1) feltételének sérülését. Várt átadandó eredmény: rövid indoklás a jól definiáltság meghiúsulásával.
F3 (implementációs, nehézség 2). Írjon
check_group_split(meta) függvényt, amely egy
index,scene_id,split oszlopokat tartalmazó pandas
DataFrame-re visszaadja azon scene_id értékek listáját,
amelyek egynél több splitbe esnek, és tesztelje a 4. szakasz hat során,
valamint egy hibás változaton. Várt átadandó eredmény: a függvény kódja,
a két hívás és a visszaadott értékek.
F4 (hibakeresési, nehézség 2). A következő kódrészlet képszintű indexeket sorsol, majd a kapott indexeket nevezi csoportos splitnek:
order = np.random.permutation(np.unique(meta["index"]))Mi a hiba, mi a következménye a GlyphLabben, és hogyan javítjuk úgy, hogy a scene legyen a sorsolási egység? Várt átadandó eredmény: a hiba lokalizálása, a következmény a két view szétválására, és a javított sorsolási sor, valamint a visszaellenőrzés módja.
F5 (kísérleti/transzfer, nehézség 3). Válasszon egy tetszőleges külső képadatkészletet, és töltse ki az 5.2. szakasz tízlépéses protokollsablonját. Adja meg a megfigyelési egységet, a licencvizsgálat tervét, a duplikátum- és annotáció-ellenőrzést, valamint a split utáni auditparancsot. Várt átadandó eredmény: a teljes terv szövege, nem letöltött adat; a letöltés hiánya kifejezetten jelölendő.
F1. A tartalom-duplikátum kritériuma
azonos felbontású, csatornaszámú tenzorokra; ez a bájtszintű azonosságot
méri. A függő pár akkor áll fenn, ha
ugyanazon jelenethez, beteghez vagy felvételhez tartozik: a két GlyphLab
view közös geometriai előfutárból származik, de a view-specifikus zaj
miatt eltérő pixelsorokat kap, tehát általában nem tartalom-duplikátum.
Az ellenpélda: legyen a generátor egy olyan futtatása, amelyben mindkét
view-ra nulla zaj jut; ekkor a pixelsorok azonosak, ám az
(index, scene_id, view_id) rekordkulcs különbözik, ezért a
rekord-duplikátum nem áll fenn. A megkülönböztetés gyakorlati
következménye: a duplikátum eltávolításakor a content hash törölheti a
függő párokat, ha a rekordkulcs nincs bevonva.
F2. Tegyük fel, hogy létezik . Ekkor , de , tehát egyszerre két különböző érték, ami ellentmondás. Az (1) feltétel sérülése: , de . A jól definiáltság bizonyításának az a lépése hiúsul meg, amely a reprezentáns függetlenségét használja; az csoportnak nincs egyetlen splitértéke.
F3. Lehetséges megoldás:
import pandas as pd
def check_group_split(meta: pd.DataFrame) -> list:
# meta oszlopai: index, scene_id, split
nsplit = meta.groupby("scene_id")["split"].nunique()
return list(nsplit[nsplit != 1].index)
# 4. szakasz hat soros, helyes példája
good = pd.DataFrame({
"index": [0,1,2,3,4,5],
"scene_id": ["S00","S00","S01","S01","S02","S02"],
"split": ["train","train","train","train","val","val"],
})
print(check_group_split(good)) # []
# hibás: az S02 egyik view-ja train lett
bad = good.copy()
bad.loc[5, "split"] = "train"
print(check_group_split(bad)) # ['S02']A visszaadott üres lista a csoportos tulajdonság teljesülését
jelenti; a hibás példában az S02 azonosítja a sértő
csoportot.
F4. A hiba: a kód a meta["index"]
egyedi értékeit sorsolja, nem a meta["scene_id"] egyedi
értékeit. A sorsolás maga nem tesz csoportos splitet; az eredmény
véletlenül sem garantálja, hogy az azonos scene_id-hez
tartozó view-k azonos splitbe kerülnek. A GlyphLabben ez azt jelenti,
hogy ugyanannak a jelenetnek az egyik view-ja a train, a másik a val
halmazba kerülhet, így a validációs hibát a trainben látott jelenet
torzítja, és a független egységek száma helytelenül a képszám lesz.
Javítás: a jelenetazonosítókat sorsoljuk, majd az eredeti indexeket a
sorsolt scene_id-k alapján válogassuk:
scenes = np.unique(meta["scene_id"])
np.random.seed(42)
val_scenes = set(np.random.permutation(scenes)[: len(scenes) // 5])
train_idx = meta.index[~meta["scene_id"].isin(val_scenes)].to_numpy()
val_idx = meta.index[meta["scene_id"].isin(val_scenes)].to_numpy()
# visszaellenőrzés
assert meta.loc[train_idx].groupby("scene_id")["split"].nunique().eq(1).all()
assert meta.loc[val_idx].groupby("scene_id")["split"].nunique().eq(1).all()A visszaellenőrzés után minden jelenet egy splitbe esik; a képindexek szétválasztása már a csoportos döntést követi.
F5. Megoldásminta a CIFAR-10 választásához. A terv
első pontja: képek osztályozása tíz osztályba, bemenet
float32 tenzor. A forrás- és licencpontba a ténylegesen használt tükröt
és annak licencét kell írni; a minta itt kifejezetten üresen hagyott
ellenőrzési mezőket tartalmaz, mert a jelen kézirat nem végzett
letöltést. A megfigyelési egység: a kép, feltéve, hogy az adatkártya nem
közöl olyan csoportosítást, amely egy forrásból több képet rögzít; ezt
az adatkártya tényleges olvasása után kell megerősíteni.
Duplikátum-ellenőrzés: a teljes archívum SHA-256-jának és a kibontott
képfájlok perceptual hash-ének összevetése; annotáció: az osztálycímke a
terjesztő leképezése szerint 0–9. Split: a csoportos tulajdonságot a
képazonosító szintjén ellenőrizzük, és a kiválasztott splitet a fenti
check_group_split-hez hasonló függvénnyel zárjuk. A közölt
korlát: a kapott modellhiba a választott tüköradatra vonatkozik, nem a
„CIFAR-10” név által jelölt bármely másolat univerzumára.
Önellenőrzés: (1) A csoportos split tulajdonság a rekordok sorrendjétől független? Igen, mert (1) indexpárokra feltétel. (2) A SHA-256 egyezés önmagában bizonyítja a jogosultságot? Nem, csak a változat azonosságát; a licenc külön rekord. (3) Két pixelszinten azonos view duplikátum-e? Tartalom szerint igen, rekordszinten nem, ha a rekordkulcs különbözik.
Korábbi fogalmak: az 5.4. Függő képek, seedek és
resampling csoportos splitje itt a lemmában kap reprezentációs
alakot: a
felírás pontosan azt rögzíti, hogy a split a jeleneteken definiált. A 10.1. Számítási gráf és lokális derivált számítási
gráfjában a közös paraméterre több ágról érkező gradiens összegzése
analóg azzal, ahogyan egy közös scene_id-t több adatrekord
hivatkozik: a hivatkozás integritását mindkét irányból, a kulcson át
kell ellenőrizni. A 21.1. Inicializálás és
varianciaterjedés inicializálási seedje a provence-rekordban tér
vissza: a generátor seedje nélkül a manifest csak statisztika, nem
reprodukálható szerződés. Végül a 18.1. Reziduális
blokk és identitásút identitásútjának tanulsága is ideillik: ahogy a
reziduális blokkban az
-út
megőrzi az azonosítást, az adatfolyamban az
index–scene_id hivatkozás őrzi meg a rekord
azonosságát a transzformációkon át.
Az adat használatának első szerződése a provenance, a licenc és a megfigyelési egység hármasa. A provenance a generáló folyamatot, seedet és lenyomatot rögzíti; a licenc a konkrét változathoz tartozó jogosultság, nem a név következménye; a duplikátum tartalom- és rekordszinten más fogalom, mint a függő nézetpár. A GlyphLabben a statisztikai egység a jelenet, ezért a split a 180 jelenet partíciója, nem a 360 képé. A lemmában belátott reprezentáció és a címke-hivatkozás injektivitása a split- és annotáció-ellenőrzés két invariánsa. A labor a manifestet és a metadata-t ezen invariánsok mentén auditálja.
A 22.2. Címkemegőrző transzformációk a címkemegőrző transzformációkat vizsgálja: ott az itt rögzített hivatkozás-egyediségre építve azt kérdezzük, mely kép- és annotációtranszformációk őrzik meg a címkét, és miért nem címkemegőrző a GlyphLabben a 90°-os forgatás.
data/manifest.json,
data/metadata.csv, a könyv ADATOK.md szerződése
szerint.