Ebben az alfejezetben egyetlen megfigyelés logitvektorából stabil módon számítunk normalizált pontszámot (softmax) és többosztályos cross-entropy veszteséget, majd levezetjük a logit szerinti gradienst: . Az előismeret a 7.1. Entrópia, cross-entropy és KL alfejezetben bevezetett diszkrét cross-entropy és KL, a 3.2. Mátrixszorzás és affín réteg alfejezetbeli affin réteg, valamint a 6.2. Konvexitás és sima optimalizálási határ alfejezetbeli gradienslépés. Induló kérdés: ha float32-ben, miért nem számolhatjuk a softmaxot a közvetlen kiértékelésével, és miért nem segít önmagában a softmax a stabil veszteséghez?
Definíció (logit). Legyen az osztályok száma. Egy megfigyelés logitvektora , ahol a -edik osztály aktiváció előtti pontszáma; a indexet a könyv jelölési szerződésének megfelelően között használjuk, mert a PyTorch célindex is 0-tól indul. A batchelt logit , egy megfigyelés egy sor.
Definíció (softmax). A leképezés A kimenetre és , tehát diszkrét valószínűségi vektorként értelmezhető. A softmax invariáns a konstans eltolásra: , mert a számláló és a nevező is -vel szorzódik. Ez az invariancia a gradiensre is öröklődik.
Definíció (logsumexp). A logsumexp függvény Ez a softmax nevezőjének logaritmusa. A név gyakori angol rövidítése: logsumexp. A log természetes alapú, ahogy az egész könyvben.
Integer target és one-hot. Az osztályozási cél egész index (PyTorchban int64). Az one-hot vektor A batchelt cél , a hozzá tartozó one-hot mátrix , ahol .
Definíció (egy megfigyelés cross-entropy-ja logitsból). A predikció és a célindex esetén Mivel minden valós -re, a függvény mindenhol értelmes.
Stabil LSE. A
közvetlen kiértékelése float32-ben már
fölött inf-et ad, pedig a softmax és a veszteség jól
definiált. Legyen
.
Ekkor
Itt minden
,
ezért
,
az összeg
és
közé esik, tehát a számítás nem csordul túl. A stabil veszteség ezzel
Ha
,
akkor a veszteség
.
A batchelt logitokra
és a
célra a softmax soronként számolandó, azaz
.
Az átlagolt (mean) cross-entropy
A [D07] dokumentáció szerint a PyTorch
torch.nn.CrossEntropyLoss logits bemenetet vár, egész
osztályindex célját fogadja el, és a reduction paramétere
'mean' (alapértelmezés), 'sum' vagy
'none'. A 'none' mintánkénti veszteségvektort
ad; a 'sum' a fenti összeg
nélkül.
Lemma (cross-entropy logitgradiense). Legyen , , és . Ekkor A gradiens alakja , megegyezik alakjával.
Bizonyítás. Rögzítsük -t, és írjuk , így . A softmax Jacobi-eleme a hányados- és láncszabályból: mert és . Ezután a összetett függvényre a láncszabály: Az utolsó egyenlőséget esetszétválasztással ellenőrizzük: ha , akkor ; ha , akkor . Mindkét eset éppen . A parciális deriváltat vektorba gyűjtve . A shape-ellenőrzés: és is -beli, így a különbségük is. A lemma feltétele minden -ra teljesül, mert a softmax nevezője pozitív.
Következmény (batch-átlag gradiense). Ha
a soronkénti softmax kimenet és
a one-hot mátrix, akkor a mean redukciójú veszteség gradiense
A 'sum' redukció esetén
ugyanez
nélkül. A levezetés a Lemma mintánkénti alkalmazásából és a véges összeg
linearitásából adódik. A gyakorlatban a keretrendszer az upstream
gradienst
szerint is skálázza: ha a veszteséghez egy további skalár szorzó
kapcsolódik, a VJP
.
A softmax kimenet formálisan diszkrét eloszlás, ezért sokan „valószínűségnek” nevezik. Ez a lépés heurisztika, nem bizonyított kalibrációs állítás. A cross-entropy minimalizálása a célosztály log-valószínűségét növeli, és ideális, végtelen mintás feltételek mellett a feltételes osztályeloszlást közelítheti; a véges mintán tanított modell azonban lehet túl magabiztos vagy alulmagabiztos. A kalibráció azt méri, hogy a -es konfidencia átlagosan -ban helyes-e. Ennek előképe éppen az itt definiált , de a tényleges kalibrációs elemzés külön metrikát (például ECE, reliability diagram) és független tesztadatot igényel; ezt a 23.2. Kalibráció és döntési küszöb alfejezetben tárgyaljuk.
Legyen , és . Az exponenciális értékek ezért . A softmax: A veszteség . A gradiens Ellenőrzés: a célosztály gradiense negatív, tehát a gradienslépés növeli -t, a többi logitot pedig csökkenti, ahogy a 6.2. Konvexitás és sima optimalizálási határ alfejezetben megismert csökkenési iránytól várható.
A következő kódot a hallgató futtatja; az itt közölt kimenet a
képletekből számolt várt érték, nem mért futás. A fájl a
lab/n026/check_ce_grad.py munkakönyvtárban van, CPU-n,
float64-ben; véletlen seed nem szükséges.
# lab/n026/check_ce_grad.py
import numpy as np
def lse(z):
c = np.max(z)
return c + np.log(np.sum(np.exp(z - c)))
def softmax(z):
s = np.exp(z - np.max(z))
return s / np.sum(s)
def ce_loss(z, y):
return -z[y] + lse(z)
def ce_grad(z, y):
e_y = np.zeros_like(z)
e_y[y] = 1.0
return softmax(z) - e_y
z = np.array([2.0, -1.0, 0.5], dtype=np.float64)
y = 2
print("z =", z)
print("softmax =", softmax(z))
print("loss =", ce_loss(z, y))
g = ce_grad(z, y)
print("analytical grad =", g)
eps = 1e-5
num = np.zeros_like(z)
for i in range(z.shape[0]):
e_i = np.zeros_like(z)
e_i[i] = 1.0
num[i] = (ce_loss(z + eps * e_i, y) - ce_loss(z - eps * e_i, y)) / (2.0 * eps)
print("numerical grad =", num)
print("max abs diff =", np.max(np.abs(num - g)))
shift = 1000.0
zs = z + shift
print("shifted loss =", ce_loss(zs, y))
print("shifted softmax =", softmax(zs))
print("shifted grad =", ce_grad(zs, y))Számított várt kimenet (kerekítve, float64-ben a hiba körülbelül
nagyságrendű): a softmax
,
a veszteség
,
az analitikus gradiens
,
a numerikus gradiens ugyanez, a max abszolút eltérés
alatti; az eltolt esetben a veszteség, a softmax és a gradiens azonos az
eltolás előttivel. A futtatási parancs:
python lab/n026/check_ce_grad.py. A központi differencia
mellett a truncációs hiba
,
float64-ben a kerekítési hiba nem dominál.
A [D07] dokumentáció szerint a PyTorch CrossEntropyLoss
logits bemenetet vár, és belül végzi el a stabil softmax + log
műveletet. Ha a felhasználó előre alkalmazza a
torch.softmax-ot, akkor a loss a már normalizált értékre
újra softmaxot számít, tehát a ténylegesen minimalizált függvény nem a
kívánt
.
Ellenpélda:
,
.
A helyes veszteség
.
Ha előbb softmaxot számítunk,
,
és ezt logitsként átadva a loss belül újra normalizál, így
.
A két érték nem azonos. Nagy logitoknál a hiba még súlyosabb:
float32-ben a közvetlen softmax
esetén
-t
adhat, a log pedig
-t;
a stabil logits-alapú loss viszont véges marad.
F1 (fogalmi, nehézség 1). Magyarázd el, mi a különbség a softmax és a logsumexp szerepe között a stabil cross-entropy-ban. Miért nem elegendő önmagában a softmax stabil számítása esetén?
F2 (levezetési, nehézség 2). Vezesd le a speciális esetben, hogy esetén a logitgradiens . Írd át a gradienst a logisztikus szigmoiddal, ahol , és indokold, miért negatív az első komponens.
F3 (implementációs, nehézség 2). Írj
stable_ce_grad(z, y) Python-függvényt, amely float64
bemenetre visszaadja a loss-t és a gradienst. Teszteld
,
esetén; hasonlítsd össze a közvetlen
implementációval (ha az nem overflowol), és adj meg numerikus
toleranciát.
F4 (hibakeresési, nehézség 2). Adott a következő hibás sor:
loss = nn.CrossEntropyLoss()(torch.softmax(logits, dim=1), target)Lokalizáld a hibát, írd le a következményét, add meg a javított sort,
és ellenőrizd a javítást logits=[[1.0, 0.0]],
target=[0] esetén.
F5 (kísérleti/transzfer, nehézség 3). Tervezz kísérletet a GlyphLab 24×24-es képosztályozó adatán: egy tanított CNN logitjaira számíts reliability diagramot és várható kalibrációs hibát (ECE) a test spliten. Add meg a protokollt, a megfigyelési egységet, a baseline-t és a következtetési korlátot.
F1. A softmax normalizált
vektort ad, de a cross-entropy
számításához a nevező logaritmusára is szükség van; nagy logitoknál a
közvetlen kiértékelése túlcsordul, ezért a
-t
a maximális elem kiemelésével számoljuk. A softmax maga is
stabilizálható a
trükkel, de így csak
-t
kapjuk; a
előállításhoz az LSE-t külön, a
kiemeléssel kell számolni. A
esetben a közvetlen
float32-ben inf, így a softmax (nan, nan)
lehet, míg a stabil LSE a
értékekkel dolgozik.
F2. Az általános lemma speciális esete: , tehát . Ekkor . A logisztikus szigmoiddal és ; pontosabban , ezért a gradiens . Mivel mindig, az első komponens pozitív, tehát a gradiens -t csökkenti, -et pedig növeli, amikor a cél az 1. osztály; ez összhangban van a cross-entropy minimalizálásával. A levezetés feltétele minden valós -re teljesül.
F3. Az elvárt függvény:
import numpy as np
def stable_ce_grad(z, y):
z = np.asarray(z, dtype=np.float64)
c = np.max(z)
log_norm = c + np.log(np.sum(np.exp(z - c)))
loss = -z[y] + log_norm
e_y = np.zeros_like(z)
e_y[y] = 1.0
p = np.exp(z - c) / np.sum(np.exp(z - c))
return loss, p - e_y
# teszt
z = np.array([1000.0, 999.0, 1000.5])
y = 2
loss, grad = stable_ce_grad(z, y)
print(loss, grad)A várt érték: a
eltolás-invarianciája miatt ugyanaz, mint a
esetben; a loss
számítható stabilan, értéke
körül, a gradiens pedig
.
A közvetlen
NumPy float64-ben még nem overflowol, de float32-ben igen; a tolerancia
a stabil és közvetlen számítás között float64-ben
abszolút eltérés alatt van. A függvény visszatérési értéke
(loss, grad) float64.
F4. A hiba oka, hogy a CrossEntropyLoss
logitsot vár, nem normalizált valószínűségi vektort. A
torch.softmax előzetes alkalmazása kettős normalizálást
okoz, és a tényleges veszteség nem a kívánt
.
Javítás: loss = nn.CrossEntropyLoss()(logits, target).
Ellenőrzés: logits=torch.tensor([[1.0,0.0]]),
target=torch.tensor([0]). A helyes loss
;
a hibás változat
.
A javított sor a [D07] szerinti szerződést teljesíti.
F5. Protokollvázlat: (1) rögzítsük a GlyphLab splitjét (train/val/test, scene_id szerint); tanítsunk egy fix CNN-t trainen, válasszunk best checkpointot val szerint. (2) A test 60 képén, tehát 30 független scene-en számítsuk a softmax kimenet konfidenciáját; a megfigyelési egység a scene, mert a két nézet függő. (3) A reliability diagramhoz binekjük a konfidenciákat 5 egyenlő szélességű intervallumba, és ábrázoljuk az átlagos konfidencia–pontosság párokat. (4) Az ECE a binenkénti átlag konfidencia pontosság súlyozott átlaga; baseline lehet egy konstans prior (osztálygyakoriság) predikció. (5) Korlát: a 60 képből 30 független scene kevés, az ECE becslése zajos; a 24×24-es szintetikus adat nem természetes képi kalibrációt mér. A kísérlet nem igényel GPU-t; CPU float32 elegendő. A konfidencia itt a softmax kimenet, de a kalibráció a 23.2. Kalibráció és döntési küszöb alfejezetben tárgyalt külön metrika.
Ellenőrizd, hogy a softmax kimenet komponensei pozitívak és összegük 1; a gradiens a célosztályon , máshol ; a batch-átlag gradiense a alakú; a stabil LSE a kiemeléssel nem overflowol. Visszahívás: a 7.1. Entrópia, cross-entropy és KL alfejezetben a cross-entropy volt, itt az one-hot cél, a softmax kimenet; a 3.2. Mátrixszorzás és affín réteg alfejezetben az affin réteg adta a logitot, itt a loss annak kimenetére épül; a 6.2. Konvexitás és sima optimalizálási határ alfejezetben a gradienslépés iránya volt a csökkenés feltétele, és a most levezetett gradiens adja a tényleges lépésirányt.
A softmax a logitvektort diszkrét eloszlássá alakítja, és invariáns a
konstans eltolásra. A többosztályos cross-entropy logitsból
alakban stabilan számítható; az LSE-t a maximális logit kiemelésével
értékeljük. Egy megfigyelésre a logitgradiens
,
ahol
a softmax kimenet és
a cél one-hot vektora; batchelt mean redukciónál
.
A CrossEntropyLoss logitsot és int64 célindexet vár,
előzetes softmax hibás. A softmax kimenet kalibrációs előkép, de
önmagában nem bizonyított kalibráció. A labor kézi háromlogitos példán,
véges differenciával és
-es
eltolással ellenőrzi a gradienst. A következő alkalmazás a 7.3. Bináris, multilabel és regressziós cél
alfejezetben a bináris és multilabel veszteség.