Ebben az alfejezetben egy már betanított, nagyobb „tanár” (teacher)
háló viselkedését préseljük át egy kisebb „diák” (student) hálóba. A
desztilláció lényege, hogy a diák nemcsak a merev osztálycímkét, hanem a
tanár lágyított osztályeloszlását is megpróbálja utánozni. Előismeret:
többosztályos cross-entropy és logit fogalma 7.2.
Softmax és többosztályos cross-entropy, valamint a
tanítási/kiértékelési mód megkülönböztetése 12.1.
Tanítás, validáció és kiértékelési mód, 18.2.
Batch normalization train és eval módban. Induló kérdés: ha egy 3
osztályos feladatban a címke 0, akkor a
(1,0,0) cél miért hordoz kevesebb mintázatot a tanuló
számára, mint egy (0.78, 0.15, 0.07) eloszlás?
Legyen a batch méret , az osztályok száma . A tanár logit kimenete
a diák logit kimenete
A valódi osztálycímke . A hőmérséklet (temperature) egy pozitív valós skalár, . A lágyított tanári cél (soft target) a soronkénti hőmérsékletes softmax:
A diák megfelelő eloszlása ugyanezzel a -vel:
A desztillációs loss a következő konvenciót követi:
ahol , és a két tag definíciója
Mindkét tag batch-átlag, tehát a loss egyetlen skalár. A
tag a PyTorch CrossEntropyLoss
reduction='mean' konvenciójának felel meg logit bemenettel
és int64 célindexszel. A KL tagban
rögzített cél,
a diák függvénye. Gyakori ekvivalens alternatíva a cross-entropy
használata a KL helyett; a kettő gradiense a diák paramétereiben azonos,
mert
,
és
a diák paramétereitől független konstans. A loss értéke
viszont eltér, ezért a naplózáskor meg kell nevezni, melyiket
számoljuk.
A tagot hard-label tagnak, a KL tagot soft-target tagnak nevezzük. A a soft tag súlya; tisztán soft desztilláció, a szokásos felügyelt tanítás. A esetén a soft tag a szokásos, nem lágyított softmaxeloszlások KL-divergenciája.
Teacher eval. A tanár súlyai a desztilláció során
nem frissülnek. A soft célok előállításakor a tanárt eval()
módba kell tenni, és torch.no_grad() alatt kell futtatni.
Ez azért lényeges, mert dropout és BatchNorm esetén a train mód más
kimenetet ad, mint az eval mód 18.2. Batch
normalization train és eval módban; a soft céloknak azt az eloszlást
kell reprezentálniuk, amelyet a tanár a kiértékeléskor produkál.
Először a gradiensről mondunk ki egy lemmát.
Lemma. Legyen rögzített, , ahol . Ekkor
Bizonyítás. A KL definíciójából
Az első tag -től független, ezért eltűnik a gradiensképzésnél. Marad a tag. A softmax logaritmusának parciális deriváltja
ahol a Kronecker-delta. Ezt behelyettesítve
mert . Ezzel a lemma bizonyítását befejeztük.
Most helyettesítsük be és értékeket. Ekkor a tanári, a diákhőmérsékletes eloszlás. A láncszabály szerint, mivel és a keresztderiváltak nullák,
A (2) képlet a pontos, véges -re érvényes gradiens. A -es szorzó nélkül a soft tag gradiense -vel skálázódik. Miért éppen a szokásos kompenzáció? Ennek indoklása a nagy határesetből látható. Fejtsük sorba a hőmérsékleti softmaxot szerint. Legyen egy logitvektor átlaga. Ekkor
ahol a maradéktag valamilyen konstanssal, feltéve, hogy a logitok komponensei korlátosak. Így esetén
ahol a kivonás és az átlag komponensenként értendő. Ezt (2)-be helyettesítve a skálázatlan KL gradiens aszimptotikus alakja
A logit-térbeli gradiens nagyságrendje tehát -tel csökken. Ha a soft tagot -tel szorozzuk, akkor a gradiens
ami esetén már -független határértékhez tart. A -es szorzó tehát azt biztosítja, hogy a hőmérséklet növelése ne hígítsa fel a soft tag tanító jelét. Pontosabban: az (1)-beli a loss értékét skálázza; a láncszabály miatt a gradiensre gyakorolt hatása ugyanez a szorzó. A fenti határérték-állítás aszimptotikus heurisztika, nem minden -re pontos egyenlőség; a véges -re érvényes igazság a (2) képlet. Ez a levezetés a saját konvenciónkra vonatkozik; az eredeti desztillációs javaslatban is hasonló skálázás szerepel [P26], de annak részletes szakaszát a kézirat írásakor nem áll módunkban teljes szövegként idézni.
Legyen , , , . A tanár logitja
a diák kezdeti logitja
és a valódi címke . Először a hőmérsékleti softmaxok. A tanári cél:
az összeg , így
A diák hőmérsékleti eloszlása hasonlóan:
az összeg , tehát
A KL tag:
A -es szorzóval a soft tag . A hard-label tag a softmaxból: , így
A teljes loss:
A gradiens ellenőrzéséhez használjuk a (2) képletet és a lemma bizonyítását. A soft tag -es gradiensére
A hard tag gradiense a szokásos softmax-cél különbség:
A teljes gradiens -súlyozva:
Az alábbi kód ugyanezt a veszteséget és gradienst számítja ki numerikusan; a kézirat írásakor ezt a kimenetet nem futtatott mérésként, hanem a fenti kézi számításból adódó várható értékként jelöljük.
# lab/n136_distill/soft_target_example.py
import torch
import torch.nn.functional as F
def distillation_loss(z_s, z_t, y, T, alpha):
"""
z_s, z_t: (N, K) logit tensorok
y: (N,) int64 osztalyindex
T: pozitiv float
alpha: float [0,1], a soft tag sulya
"""
q = torch.softmax(z_t / T, dim=1)
log_p = torch.log_softmax(z_s / T, dim=1)
kd = F.kl_div(log_p, q, reduction='batchmean')
ce = F.cross_entropy(z_s, y, reduction='mean')
return alpha * T * T * kd + (1.0 - alpha) * ce
torch.manual_seed(20261020)
z_t = torch.tensor([[2.5, 0.0, -0.5]], dtype=torch.float64)
z_s = torch.tensor([[1.2, 0.3, -0.9]], dtype=torch.float64, requires_grad=True)
y = torch.tensor([0], dtype=torch.int64)
loss = distillation_loss(z_s, z_t, y, T=2.0, alpha=0.7)
loss.backward()
print(f"loss={loss.item():.4f}")
print(f"grad={z_s.grad.detach().numpy()}")A várt kimenet loss=0.2862 és
grad=[[-0.3268, 0.2632, 0.0636]] körül, körülbelül
abszolút toleranciával, mert a kézi számítás négy tizedesjegyre
kerekített.
A következő mérési terv a GlyphLab adatszerződést használja. A tanár és a diák is ugyanazt a train/val/test felosztást kapja, és a modellválasztás kizárólag a clean validációs loss alapján történik, ahogyan azt 22.4. Augmentációs kísérlet és domainváltozás előírja. A kézirat írásakor ezt a kísérletet nem futtattuk, ezért alább csak a protokollt és a desztilláció-specifikus kódvázlatot adjuk meg; a kimeneti számok a fenti kézi példa ellenőrzésére szolgálnak.
Protokoll.
data/images.npy train részén, 240 képen, seed
20261020, Adam, tanulási ráta
,
batch 32, legfeljebb 20 epoch. A legjobb checkpointot a val loss
választja ki.eval() módban, torch.no_grad() alatt futtatjuk
a train és val képekre. A kapott
logit tenzort float32 tömbben elmentjük. A tanár a diák
tanítása alatt nem fut újra.corrupted_test.npy
halmazra. A két halmaz ugyanazon scene/view párokból áll, ezért a
clean–corrupt pontosságkülönbség páros, jelenetszintű összehasonlítás 22.4. Augmentációs kísérlet és domainváltozás. A
teachert is ugyanígy kiértékeljük összehasonlításként.torch.utils.benchmark [D16] és a
torch.profiler [D17] használható; a mérési környezetet, az
eszközt és az egyes profilozási beállításokat minden futtatáskor a
laborjelentésben kell rögzíteni.A desztilláció-specifikus kódvázlat:
# lab/n136_distill/train_distill.py
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
torch.manual_seed(20261020)
np.random.seed(20261020)
images = np.load("../data/images.npy") # (360,1,24,24) float32
labels = np.load("../data/labels.npy") # (360,) int64
# ... train/val/test indexek a metadata.csv split oszlopa alapjan ...
def make_soft_cache(teacher, split_images):
teacher.eval()
with torch.no_grad():
# split_images: (M,1,24,24) float32 CPU tensor
logits = teacher(split_images) # (M,3)
return logits.detach().cpu().float() # soft target cache
def distillation_loss(z_s, z_t, y, T, alpha):
q = torch.softmax(z_t / T, dim=1)
log_p = torch.log_softmax(z_s / T, dim=1)
kd = F.kl_div(log_p, q, reduction='batchmean')
ce = F.cross_entropy(z_s, y, reduction='mean')
return alpha * T * T * kd + (1.0 - alpha) * ce
# ... a tanitasi hurok a n044 szerinti szerkezetet koveti; a teacher
# forwardja helyett a cache-bol toltjuk a z_t-t ...Futtatási parancs a munkakönyvtárból:
cd lab/n136_distill
python train_distill.py --T 4 --alpha 0.7 --seed 20261020Az átadandó eredmény: tanári és diák val pontosság, clean test pontosság, corrupt test pontosság, valamint a corrupt–clean páros különbség átlaga és szórása. Értelmezési korlát: a GlyphLab 24×24 pixeles procedurális adat, ezért az eredmény nem általánosít természetes képi feladatokra.
Magyarázza el, miért nem azonos a desztilláció a label smoothinggal. Adjon egy osztályú, példát, amelyben a tanári soft cél , a valódi címke , és mutassa meg, hogy a egyenletes hátterű label smoothing cél ettől különbözik.
Bizonyítsa be a fenti lemma felhasználásával, hogy az (1) loss-ban a soft tag gradiensére
teljesül. Ellenőrizze a képletet a kézi példa , adataira, és adja meg a kapott háromdimenziós gradiensvektort.
Implementálja a distillation_loss függvényt úgy, hogy ne
használja a torch.nn.KLDivLoss osztályt, hanem a KL tagot a
definícióból számolja. A függvény bemenete z_s,
z_t, y, T, alpha; a
kimenet skalár. Ellenőrizze a kézi példán: z_s,
z_t, y, T=2.0,
alpha=0.7 mellett a loss
.
Az alábbi részlet hibásan állítja elő a soft célokat:
teacher.train()
with torch.no_grad():
z_t = teacher(x_batch) # (N,3)
q = torch.softmax(z_t / T, dim=1) # soft target
# ... studenttanítási lépés ...
# a teacher súlyai nem frissülnek, de a BatchNorm statisztikája train módbanNevezze meg a hiba okát, írja le a következményét a desztillált diák tanítására, javítsa a kódot, és adja meg, hogyan ellenőrizné a javítás helyességét.
Tervezzen kísérletet, amely a GlyphLabon a hard-label baseline-t egy , és desztillált studenttel hasonlítja össze, mindegyiket 3 különböző seeddel. Adja meg a megfigyelési egységet, a splitet, a modellválasztási szabályt, a metrikát, a számítási és címkeköltség-keretet, valamint a következtetés érvényességi korlátját.
A label smoothing a valódi one-hot cél helyett a
eloszlást használja; ez a háttérosztályokat szimmetrikusan, egyenletesen tölti fel, és nem függ egyetlen tanár predikciójától sem. A desztilláció ezzel szemben egy konkrét tanár által számított eloszlást használ célként, amely tükrözheti a tanár osztályok közötti hasonlósági ítéletét. A megadott és esetén a smoothing cél
amely különbözik a tanári -tól: a tanár a 2. osztályt kissé valószínűbbnek tartja a 0. osztálynál, míg a smoothing ezt a kettőt egyenlővé teszi.
A lemma szerint a KL gradiens a diák hőmérsékleti logitjaira , ahol . A láncszabállyal
A loss -szeres szorzót tartalmaz, ezért
A kézi példában , így
# lab/n136_distill/manual_kd.py
import torch
import torch.nn.functional as F
def distillation_loss_manual(z_s, z_t, y, T, alpha):
q = torch.softmax(z_t / T, dim=1)
p = torch.softmax(z_s / T, dim=1)
# numerikusan stabilabb: q*(log q - log p)
kd = torch.sum(q * (torch.log(q + 1e-12) - torch.log(p + 1e-12)), dim=1).mean()
ce = F.cross_entropy(z_s, y, reduction='mean')
return alpha * T * T * kd + (1.0 - alpha) * ce
torch.manual_seed(20261020)
z_t = torch.tensor([[2.5, 0.0, -0.5]], dtype=torch.float64)
z_s = torch.tensor([[1.2, 0.3, -0.9]], dtype=torch.float64, requires_grad=True)
y = torch.tensor([0], dtype=torch.int64)
loss = distillation_loss_manual(z_s, z_t, y, T=2.0, alpha=0.7)
print(float(loss))Az ellenőrzés: a kézi számítás 0.2862; a kódnak ezt kell
visszaadnia
abszolút hibán belül. A 1e-12 hozzáadás csak az üres
logaritmus elkerülésére szolgál; float64 bemenetnél a négy
tizedesjegyre kerekített kézi értékhez képest a hiba
.
Hiba oka: a tanárt train() módban
hagytuk, ezért a BatchNorm rétegek a minibatch-átlagot és varianciát
használják, nem a tanítás során gyűjtött running statisztikát. Ráadásul
a no_grad csak a gradiens számítását kapcsolja ki, a BN
training flagjét nem.
Következmény: a soft célok batch-függővé válnak; ugyanahhoz a képhez különböző minibatch-összetétel mellett más tartozhat. A diák inkonzisztens célokat kap, ami a desztillációs jelet zajossá és a kiértékelési viselkedéstől eltérővé teszi.
Javítás:
teacher.eval()
with torch.no_grad():
z_t = teacher(x_batch)Ellenőrzés: futtassuk a tanárt két különböző
minibatch-be rendezett adaton; eval() módban a logitoknak
batch-átrendezéstől függetlenül azonosnak kell lenniük, míg a hibás
train() módban a BatchNorm miatt eltérhetnek.
Megfigyelési egység: a GlyphLab
scene_id, mert a két nézet ugyanahhoz a jelenethez
tartozik; a bootstrap és a páros összehasonlítás is jelenetszintű 22.4. Augmentációs kísérlet és domainváltozás.
Split: a rögzített train/val/test osztás; a corrupt
teszt csak a test scene párokra épül. Modellválasztás:
minden seedhez a clean val loss minimumánál választunk best
checkpointot; a tesztet csak ezután, egyszer értékeljük. Változó
tényező: a soft tag hőmérséklete
,
rögzített
mellett, plusz a
baseline. Metrika: clean test accuracy, corrupt test
accuracy, és a corrupt–clean páros különbség átlaga.
Költségkeret: a tanár egyszer tanul meg, és minden
diák-kísérlet ugyanannyi képcímkét használ; a számítási keret a diák
forward/backward lépéseinek számával normalizálva azonos.
Érvényességi korlát: a GlyphLab toy adat, ezért a
sorrendből nem vonható le következtetés természetes képekre; a 3 seed
csak a seed-szórás alsó becslését adja; a soft célokból nyert nyereség
nem bizonyítja, hogy a diák a tanár minden hibaszeletét megőrzi.
Gyakori tévedés, hogy a desztillált diák automatikusan megőrzi a tanár minden viselkedését, például a ritka osztályokon vagy a corrupt bemeneteken mutatott pontosságát. A desztillációs loss a soft célok átlagos KL-divergenciáját bünteti, de a diák kapacitása kisebb, és a loss nem tartalmaz szeletenkénti súlyozást. Ellenpélda: legyen egy háromosztályos feladat, amelyben az 1. osztály a gyakori, a 2. osztály pedig ritka, és a tanár a ritka osztályon 90%-os, a gyakorin 95%-os pontosságú. Ha a diák a soft célokat a gyakori osztályok mintáin jobban tudja csökkenteni, akkor előfordulhat, hogy a teljes KL alacsony marad, miközben a ritka osztály pontossága 70%-ra esik vissza. A desztilláció tehát nem helyettesíti a 33.4. Üzemeltetés, drift és késő címke alfejezetben bevezetett monitorozást és a hibaszelet-elemzést; az üzembe helyezés előtt a diákot ugyanazokkal a tesztekkel kell ellenőrizni, mint a tanárt.
A definíciók ellenőrzése: a soft cél minden sora
valószínűségeloszlás, nemnegatív és
összegű; a hard-label tag logit bemenetet vár, előtte nem végzünk
softmaxot 7.2. Softmax és többosztályos
cross-entropy. A KL csak akkor véges, ha
supportja benne van
supportjában; hőmérsékleti softmax esetén ez teljesül. A numerikus
stabilitáshoz log_softmax használata indokolt, nem külön
softmax majd log. A 34.3.
Pruning és struktúra alfejezetből tudjuk, hogy a pruning után a
ritka súlyok tényleges kihagyása külön lépés; a desztilláció a kisebb
modell előállításának alternatív útja, és a kettő kombinálható, ha a
prune-olt diákot ezután a soft célokkal finomhangoljuk. A 30.4. Önfelügyelt kísérlet korrekt összevetése
költségkerete itt is érvényes: ha a tanári logitokat címkézetlen képekre
is kiterjesztjük, akkor a címkeköltség és a teacher-forward költség
külön sorban könyvelendő, hogy a hard-label baseline-nal való
összehasonlítás fair maradjon. Végül a 22.4.
Augmentációs kísérlet és domainváltozás szerint a corrupt tesztet
csak a befagyasztott, legjobb val checkpointon értékeljük, és a
clean–corrupt különbséget páros, jelenetszintű adatként kezeljük.
A tudásdesztilláció egy kiértékelő módba kapcsolt, befagyasztott tanár lágyított osztályeloszlásait használja célként egy kisebb diák tanításához. Az (1) loss egy súlyú soft KL tagból és egy súlyú hard-label cross-entropy tagból áll. A soft tagban a tanári és diáklagitok egyaránt -vel osztottak; a lemma szerint a KL gradiens , ezért a -es szorzó a nagy határesetben kompenzálja a logit-gradiens -es csillapodását. A labor azonos tesztprotokollt ír elő a tanárra, diákra és hard-label baseline-ra, és a corrupt tesztet páros jelenetszintű adatként értékeli.
A 35.1. Saliency és Grad-CAM a Grad-CAM és a saliency-térképek alapjait tárgyalja. A desztillált diák kisebb paraméterszámú modellje alkalmas kiindulópont a magyarázatok sanity checkjéhez, mert a tanár-diák eltérések vizsgálata megmutathatja, mely bemeneti régiókban marad meg vagy vész el a tanári viselkedés.