A 21.3. Dropout, súlyregularizálás és augmentáció egységben a dropout, a weight decay és az augmentáció mellett a label smoothing is megjelent mint a cél eloszlásának módosítása. Itt azt vizsgáljuk, hogyan befolyásolja a tanulást, ha az egyes osztályok gyakorisága a tanítóhalmazban erősen eltér. A GlyphLab train halmazában mindhárom osztályból 80–80 kép van, tehát kiegyensúlyozott. Valós alkalmazásokban azonban gyakori, hogy a „vertical” osztály a megfigyelések 90%-át teszi ki, a „horizontal” és „diagonal” pedig csak 5–5%-ot. Ilyenkor a naiv empirical risk minimization a többségi osztályra optimalizál, mert a hibák átlagában a gyakori osztály dominál.
Előismeret: a cross-entropy és a softmax definíciója a 7.2. Softmax és többosztályos cross-entropy alfejezetből, a tanítási célfüggvény a 6.1. Objektív, reguláris tag és gradienslépés alfejezetből, a fair comparison és a seed–protokoll a 17.4. Architektúra összehasonlítása kontrollált keretben alfejezetből, valamint az aktivációk és a gradiensskálázás a 9.4. Aktivációk és gradiensáramlás alfejezetből.
Induló kérdés. Tegyük fel, hogy egy tanítóhalmazon az osztályarány . Mekkora súlyokat kell választanunk ahhoz, hogy a veszteség az osztályonkénti hibák súlyozatlan átlaga legyen? A választ a 3. szakasz levezetése adja meg; induló becslésként a ritka osztályok súlya a gyakori osztály súlyának nyolcszorosa.
Legyen az osztályok száma, a cél, és a modell által adott posterior valószínűség a -adik osztályra. A többosztályos cross-entropy veszteség egyetlen megfigyelésre
A modell logitsot ad ki, a softmax a loss belsejében történik a [D07] szerződés szerint; a cél int64 osztályindex.
Osztályarány és empirikus gyakoriság. A tanítóhalmaz megfigyeléséből az darab tartozik a osztályhoz, minden -ra. Az empirikus osztálygyakoriság
A populációszintű értékek általában ismeretlenek; a tanítóhalmazbeli a becslésük.
Súlyozott cross-entropy, gradient scaling konvenció. Legyen pozitív osztálysúly-vektor. A batchre vett súlyozott empirikus veszteség az
képlet, ahol a nevező a batch mérete, nem a súlyok összege. Ez a
konvenció azt jelenti, hogy a gradiensben az
osztályú példák
-szoros
szorzót kapnak. A PyTorch
CrossEntropyLoss(weight=..., reduction='mean') ezzel
szemben a
súlyozott átlagot számítja. A két mennyiség csak konstans szorzóban tér el, ha a batch súlyösszege rögzített; az optimum -ban azonos, de a gradiens léptéke és az optimáló beállítása különbözik. A fejezet a gradient scaling konvenciót használja, és minden numerikus kódban explicit módon megadja a reductiont.
Sampler. A sampler a batch összetételét változtatja meg: nem a tanítóhalmaz eredeti eloszlásával mintavételez, hanem egy megcélzott eloszlással. A leggyakoribb választás a class-balanced sampler, ahol minden -ra. Az osztályonkénti mintavételi valószínűség ekkor , így a mintavételezett batchben az osztályarány közel egyenletes lesz.
Focal loss, áttekintés. A focal loss a példánkénti nehézséget súlyozza, nem az osztályt:
Ha , visszakapjuk a standard cross-entropy-t. Ha , akkor a magas konfidenciájú, könnyen osztályozott példák relatív súlya csökken, a bizonytalan, nehéz példáké nő. A focal loss önmagában nem osztályarány-korrekció, de kombinálható osztálysúlyozással.
Kalibráció. A modell akkor jól kalibrált, ha a prediktált valószínűségek közelítik a tényleges feltételes gyakoriságot. Egy gyakorlati mérőszám az Expected Calibration Error: a validációs halmaz példáit a maximális prediktált konfidencia szerint intervallumokra bontjuk, majd binenként a konfidenciaátlag és a pontosság abszolút különbségét az elemszám arányával súlyozzuk:
A súlyozott loss vagy a sampler megváltoztatja azt az eloszlást, amelyre a modell poszteriorjait illeszti; ezért a kalibrációt a tényleges teszteloszláson, nem az eltolt tanítóhalmazon kell mérni.
Állítás (weighted ERM célfüggvény). Legyen a tanítóhalmaz , , az osztályonkénti elemszám . Definiáljuk az osztályon belüli empirikus átlagos veszteséget
A osztálysúlyokkal definiált súlyozott empirikus kockázat
Ekkor a
választás mellett
Levezetés. Bontsuk az összeget osztályonként:
Helyettesítsük be a fenti értéket:
A levezetés tisztán definíciós átrendezés; nincs szükség valószínűségszámítási konvergenciatételre. A feltételek: minden -ra, , és minden véges. A populációszintű analóg állítás ugyanígy igaz: ha a valódi ismert, akkor mellett a súlyozott kockázat a class-balanced kockázatot adja.
Milyen kockázatot minimalizálunk tehát? A súlyozatlan empirikus kockázat a mintában szereplő arányok szerinti átlag, így a többségi osztály hibája dominálja. Az iménti választással a minimalizált célfüggvény az osztályonkénti hibák súlyozatlan átlaga: minden osztály azonos súllyal szerepel. Ez a döntés akkor indokolt, ha a felhasználási szerződés szerint az osztályok egyenlő fontosságúak, például a GlyphLab kiegyensúlyozott tesztjén. Ha a teszt eloszlása valójában ugyanaz az eltolt mix, akkor a súlyozatlan ERM a helyes cél; a súlyozás ekkor a többségi osztályt alulreprezentálja.
Fontos tehát kimondani: a class-balanced súlyozás nem mindig javítja a kalibrációt vagy a valós pontosságot; a választott súlyozás a választott kockázatfüggvény. A levezetés nem állítja, hogy a súlyozás javítja a generalizációt, csak azt, hogy mit tesz a célfüggvénnyel.
Legyen , , , tehát . A class-balanced súlyok
Tegyük fel, hogy egy adott mellett az osztályonkénti empirikus veszteségek
A súlyozatlan empirikus kockázat
A súlyozott empirikus kockázat a fenti -vel
A különbség jól mutatja, hogy a súlyozott cél a ritka osztályok hibáját sokkal erősebben bünteti: a értéke több mint kétszerese a súlyozatlannak, mert a két ritka osztály átlagos hibája nagy. Ha a modell a többségi osztályra specializálódik, a súlyozatlan cél kicsi, a súlyozott nagy marad; a súlyozott optimum tehát más kompromisszumot keres.
A labor célja, hogy a class-balanced súlyozás, a sampler és a kiinduló súlyozatlan baseline hatását mérje egy mesterségesen eltolt tanítóhalmazon. A futást ez a könyv nem hajtotta végre; az alábbi kód teljes protokoll, a táblázat pedig jelölt szemléltetés, nem mért eredmény. A hallgató a saját környezetében futtatja, és a nyers eredményeket a kísérleti naplójában rögzíti.
Adat. A GlyphLab train felosztásában
osztályonként 40 jelenet, jelenetenként 2 nézet, azaz 80 kép van. A
laborhoz csoportszinten választunk osztályonként rendre 40, 5 és 5
teljes jelenetet: így 100 kép marad (80 vertical, 10 horizontal, 10
diagonal), azaz 0.8/0.1/0.1 az osztályarány. A többi 140 train képet
kizárjuk ebből a laborkísérletből. Azonos scene_id-jú két
nézet nem kerülhet különböző részhalmazba. A validációs halmaz
változatlanul a teljes 60 kép (20–20–20 osztályonként), így
kiegyensúlyozott, és a kiegyensúlyozott metrika értelmes.
Modell és recept. Ugyanaz a kis CNN, mint a 21.3. Dropout, súlyregularizálás és augmentáció laborjában. A batch méret 24, epoch 30, AdamW (lásd [P02]) tanulási ráta , seed 20261020. Minden konfigurációra öt seedet használunk (20261020, 20261021, …, 20261024), és a validációs balanced accuracy átlagát és szórását közöljük.
Konfigurációk. (1) Baseline: súlyozatlan
CrossEntropyLoss(reduction='mean'). (2) Weighted CE: súlyok
a fenti eltolt gyakoriságból. (3) WeightedRandomSampler
osztályonkénti kiegyensúlyozó mintavétellel, súlyozatlan loss
mellett.
Protokoll és kiértékelés. A modellválasztás kizárólag a validációs balanced accuracy maximumán történik. A tesztet nem használjuk a labor összehasonlításában. A kalibrációt a validációs halmazon ECE-vel mérjük, 8 egyenlő szélességű konfidenciaintervallummal.
A tanítási eljárás implementációs váza (az ... jelölésű
részeket a hallgatónak kell kiegészítenie, ezért nem önállóan futtatható
program):
# lab_084_imbalance.py — munkakönyvtár: lab/
import numpy as np
import torch
from torch.utils.data import DataLoader, WeightedRandomSampler
# images: (360,1,24,24), labels: (360,) — GlyphLab tömbök
images = np.load("data/images.npy")
labels = np.load("data/labels.npy")
meta = np.loadtxt("data/metadata.csv", delimiter=",", skiprows=1, dtype=str)
# A teljes kód a metadata split oszlopát olvassa; itt csak a váz szerepel.
def make_model():
# A n083 laborjából ismert kis CNN: Conv(1,8,k=3), ReLU, MaxPool(2),
# Conv(8,16,k=3), ReLU, MaxPool(2), Flatten, Linear(16*4*4,3)
...
def run(imbalance_idx, mode, seed):
torch.manual_seed(seed)
# mode: "base", "weighted", "sampler"
...A labor jelentésben három táblázatot kérünk: train loss utolsó epochban, validációs accuracy, balanced accuracy, macro-F1 és ECE. Példaként, nem mért futás:
| Módszer | val acc (átlag±szórás) | balanced acc | ECE |
|---|---|---|---|
| baseline | |||
| weighted CE | |||
| sampler |
A kísérleti állítást csak a tényleges futtatás után szabad megfogalmazni. A fenti táblázat pusztán a várt mintázat illusztrációja: a class-balanced módszerek általában javítják a kiegyensúlyozott metrikát, de a nyers accuracy kissé romolhat, és a kalibráció a kiegyensúlyozott validáción javulhat.
Magyarázza el, mi a lényegi különbség a loss weighting és a batch sampler hatásmechanizmusa között. Adjon egy olyan esetet, amikor a két módszer eltérő viselkedést eredményez ugyanakkora átlagos osztályarány mellett.
Legyen , , , . Írja fel a class-balanced súlyokat, és vezesse le a 3. szakasz képletéből, hogy a súlyozott empirikus kockázat valóban . Ellenőrizze az indexhatárokat, és mondja ki, melyik feltétel sérül, ha .
Írjon PyTorch-kódot, amely kiszámítja egy rögzített logit- és
célbatchre a súlyozott cross-entropy-t mind a gradient scaling
konvencióban, mind a PyTorch reduction='mean' beépített
változatában. Ellenőrizze, hogy a két érték aránya a batch
súlyösszegétől függ. Használjon torch.manual_seed(0)-t,
float32 tensort, és adja meg a kódot.
A következő kódrészlet a tanítási loop egy részlete:
# target_train: az imbalanced dataset minden példájához tartozó osztályindex
sample_weights = 1.0 / class_counts[target_train]
sampler = WeightedRandomSampler(weights=sample_weights, num_samples=len(dataset), replacement=True)
loss_fn = nn.CrossEntropyLoss(weight=1.0 / class_counts)A fejlesztő célja a class-balanced tanítás. Azonosítsa a kettős,
egymásra rakódó osztályarány-korrekciót, értelmezze a következményét, és
mutassa meg a javítást. A sample_weights minden
tanítópéldához külön súlyt ad, ezért hossza len(dataset).
Ellenőrizze a javítást egy kis logit- és célbatchre úgy, hogy kiszámítja
az osztályonkénti effektív súlyozást.
Tervezzen protokollt annak mérésére, hogy a class-balanced weighted CE javítja-e a ritka osztályok recallját egy olyan teszteloszláson, ahol a célmix 90% vertical, 5% horizontal, 5% diagonal. Adja meg a megfigyelési egységet, splitet, baseline-t, változó tényezőt, metrikákat, seed-kezelést, választási szabályt és a következtetés korlátját. Az F5 nyitott: legalább egy teljes tervet kell adni, és indokolni, miért nem elegendő a sima accuracy.
A loss weighting a célfüggvényben a gradiens osztályonkénti skáláját
módosítja: egy
súlyú osztályból származó példa hibájának gradiense
-szoros.
A batch-sampler ezzel szemben a batch összetételét változtatja: a ritka
osztály gyakrabban kerül a batchbe, így a gradienslépés nagyobb arányban
tartalmazza azt az osztályt. Az eltérés jól látszik abban az esetben, ha
a batch méret kicsi és a loss weighting mellett a ritka osztály könnyen
eltűnik a mini-batchből, mert a mintavétel továbbra is a többségi
eloszlást követi. A WeightedRandomSampler csak az egyes
húzások valószínűségét módosítja, így még kiegyensúlyozott várható
gyakoriság mellett sem garantálja, hogy minden osztály megjelenik minden
minibatchben; a loss weighting pedig csak akkor hat, ha az adott
osztályból ténylegesen szerepel példa. Ugyanakkor a loss weighting
determinisztikus célfüggvényt ad, míg a sampler a sztochasztikus
gradiens varianciáját növelheti.
, , , , , . A súlyok:
A súlyozott empirikus kockázat
Az utolsó egyenlőség onnan jön, hogy és . A súlyozott összeg tehát éppen az osztályonkénti átlagok átlaga. Ha , akkor , a osztás nullával nem értelmezett; a class-balanced súlyozás ezért csak akkor használható, ha minden osztályból van legalább egy tanítópélda. A levezetés indexhatárai az részhalmazokra a tartományon érvényesek.
# lab/f3_weighted_ce.py — futtatható lokálisan
import torch
import torch.nn.functional as F
torch.manual_seed(0)
logits = torch.randn(6, 3, dtype=torch.float32) # N x K
target = torch.tensor([0, 0, 0, 0, 1, 2], dtype=torch.int64)
train_counts = torch.tensor([80, 10, 10], dtype=torch.float32)
K = 3
# A súlyokat a TRAIN teljes osztálygyakorisága, nem ez a mini-batch adja.
w = train_counts.sum() / (K * train_counts) # shape (3,)
# 1) gradient scaling konvenció
loss_each = F.cross_entropy(logits, target, reduction='none') # shape (6,)
L_gradscale = torch.mean(w[target] * loss_each)
# 2) PyTorch beépített mean reduction súllyal
L_torch = F.cross_entropy(logits, target, weight=w, reduction='mean')
# Ellenőrzés: L_torch = sum(w_i*l_i) / sum(w_i)
L_numerator = torch.sum(w[target] * loss_each)
L_denom = torch.sum(w[target])
L_expected = L_numerator / L_denom
print(f"Gradient scaling : {L_gradscale.item():.6f}")
print(f"PyTorch mean : {L_torch.item():.6f}")
print(f"Elvárt torch mean: {L_expected.item():.6f}")
print(f"Arány : {L_gradscale.item() / L_torch.item():.6f}")
print(f"Batch súlyösszeg : {L_denom.item():.6f}")Ellenőrzés: a kimenetben a második és harmadik érték bitre azonos
kell legyen (torch.allclose). Az arány a batch súlyösszege
osztva batch mérettel. A rögzített train-gyakoriságokra
;
a hat példás minibatch négy nullás és egy-egy ritka osztálycímkéje
mellett
,
így a két érték aránya
,
nem 1. Ha a súlyokat hibásan az adott minibatch saját gyakoriságából
becsülnénk, a két normalizálás e speciális példában véletlenül éppen
megegyezne.
Hiba: a sampler és a loss weighting ugyanazt az inverse frequency
súlyozást alkalmazza egyszerre. A sampler már a batch szintjén
kiegyensúlyozza az osztályarányt, a loss súly pedig ezen felül még
-szoros
gradiensszorzót ad. Következmény: a ritka osztály kétszeresen fel van
súlyozva; az effektív osztálysúly
lesz, ahol
a sampler által beállított batchgyakoriság. Ha a sampler
osztályeloszlása várhatóan
,
és a loss súly
,
akkor a normalizálás előtti osztály-hozzájárulás
;
a célzott, egyenlő osztály-hozzájárulás ezzel szemben mindegyik
osztályra
.
Az osztályok egymáshoz viszonyított hozzájárulása ezért fordítottan
arányos lesz az eredeti
gyakorisággal. A
CrossEntropyLoss(weight=..., reduction='mean') batchszinten
a súlyok összegével oszt, ami a relatív eltolást nem szünteti meg.
Javítás: a két módszer közül csak az egyiket használjuk; ha a sampler
alkalmazása a cél, a loss maradjon súlyozatlan. Ha a loss weighting
mellett döntünk, ne használjunk mintavételező-módosítást a batchben.
Ellenőrzés: egy olyan kis batchben, ahol ismert az osztályarány,
számítsuk ki az osztályonkénti gradiens-átlag beszorzóját; a helyes
javítás után a populációszintű osztály-hozzájárulás minden osztály
esetén
,
nem a ritka osztály fordított gyakoriságával újra felskálázott
érték.
Egy lehetséges terv:
A leggyakoribb hiba a kettős korrekció: a loss weighting és a sampler ugyanazzal az osztályarányú súllyal való együttes alkalmazása indoklás nélkül. Az F4 feladatban látott effektív osztálysúly könnyen a ritka osztály túlzott felhangsúlyozásához vezet, ami túlillesztést okoz a ritka osztályon, és romolhat a kalibráció. Ellenpélda: ha a sampler közel egyenletes -t ad, és a loss súly , akkor az osztályonkénti relatív hozzájárulás , nem pedig azonos minden osztálynál. Az eredetileg ritka osztályok így a class-balanced célhoz képest is aránytalanul felértékelődnek. A kettős korrekció tehát nem azonos a class-balanced célfüggvénnyel. A helyes eljárás: válasszunk egy mechanizmust, és dokumentáljuk a döntést a kísérleti naplóban.
Önellenőrzés. Ellenőrizze, hogy a súlyok pozitívak, az összegük nem feltétlenül 1, a mini-batch loss redukciója a választott konvenciót követi, és a kalibráció mérése a cél eloszláson történik. Visszahívás: a fair comparison 17.4. Architektúra összehasonlítása kontrollált keretben szellemében a baseline és a súlyozott változat csak a vizsgált tényezőben térhet el; a seed, a batch méret, az optimalizáló és a modellválasztási szabály azonos kell legyen.
A nem egyenletes osztályarány a naiv ERM-et a többségi osztály felé tolja. A class-balanced súlyozás a veszteségben az osztályonkénti hibákat egyenlő arányban átlagolja: választással , a minimalizált célfüggvény . A sampler a batch összetételét módosítja, a focal loss példánkénti nehézséget súlyoz; a három mechanizmus nem felcserélhető. A súlyozás megváltoztatja a kalibráció cél-eloszlását, ezért az értékelést a tényleges felhasználási eloszláson kell végezni. A súlyozást és a samplert indoklás nélkül együtt alkalmazni kettős korrekció, amely túlillesztéshez vezethet.
A következő egység, 22.1. Adateredet, címke és
csoportos split, az adateredet, a címke és a csoportos split
kérdéseit tárgyalja: ott a scene_id szerinti függetlenség és az
annotációs hibák kezelése épít a fenti osztályarány- és értékelési
megfontolásokra. A súlyozott empirical risk levezetése saját definíciós
levezetés, nincs szüksége külső tételre. A PyTorch
CrossEntropyLoss súlyozási viselkedését a [D06] általános
torch.optim hivatkozás nem fedi; a fejezet a [D07]
keretjegyzet loss-szerződését és a JELOLESEK.md konvencióját alkalmazza.
A [P02] az AdamW decoupled weight decay forrása, amely a laborkísérlet
optimalizálójának megválasztásához kapcsolódik.
Felhasznált források: