23.2 Kalibráció és döntési küszöb

23.2.1 1. Cél, előismeret és induló kérdés

A 23.1. Confusion matrix és aggregálási konvenció egységben a confusion matrixból kiindulva az accuracy, precision és recall fogalmát építettük fel. Ott a döntési lépés adott volt: az argmax kiválasztja a legnagyobb logithoz tartozó osztályt. Most a döntés előtt álló valószínűségi kimenetet vizsgáljuk: ha a modell azt mondja, hogy egy kép 0,9 valószínűséggel vertical, két különböző kérdést tehetünk fel. Osztályonként: azok között a képek között, amelyekre a vertical osztály valószínűsége 0,9, tényleg kb. 90% a vertical? A döntés konfidenciájára (top-label): azok között a döntések között, amelyek legnagyobb valószínűsége 0,9 (bármelyik osztályra), kb. 90% helyes? A kettő nem ugyanaz, és mindkettő ahhoz kell, hogy a 0,9 értéket valódi valószínűségként használhassuk. Ez a kalibráció kérdése, és szorosan kapcsolódik ahhoz, hogyan állítunk be egy döntési küszöböt egy költségérzékeny alkalmazásban.

Előismeretként a 23.1. Confusion matrix és aggregálási konvenció jelölését használjuk: Z∈ℝN×KZ\in\mathbb R^{N\times K} logitmátrix, y∈{0,…,K−1}Ny\in\{0,\ldots,K-1\}^N osztályindex-vektor. A [D07] dokumentáció szerint a PyTorch CrossEntropyLoss logits bemenetet és int64 célindexet vár, a softmaxot pedig maga a loss számolja; mi itt a loss definíciójához a softmax-kimenetet explicite is felírjuk. A 11.2. nn.Module és paraméterregisztráció tanulsága, hogy a modell eval() módban, frissítés nélkül adja a kiértékeléshez használt logitokat, és a 22.2. Címkemegőrző transzformációk szerződése szerint a kalibráló halmaznak ugyanazon a preprocessingen kell átmennie, mint a tanító halmaznak.

Induló kérdés. Egy háromosztályos GlyphLab-modell a validációs halmazon minden mintához pmax=0.8p_{\max}=0.8 körüli maximális softmax-értéket rendel. Ebből következik-e, hogy az ilyen minták 80%-ában helyes az argmax-döntés? Ha nem, mit kell mérnünk, és hogyan javítható a hiba a logitok megváltoztatása nélkül?

23.2.2 2. Definíciók, alakok és intuíció

Legyen Z∈ℝN×KZ\in\mathbb R^{N\times K} a modell által adott logitmátrix. A softmax-kimenet

pn,k=exp(zn,k)∑j=0K−1exp(zn,j),p∈[0,1]N×K,∑kpn,k=1.p_{n,k}=\frac{\exp(z_{n,k})}{\sum_{j=0}^{K-1}\exp(z_{n,j})},\qquad p\in[0,1]^{N\times K},\quad \sum_k p_{n,k}=1.

A döntés ŷn=argmaxkzn,k=argmaxkpn,k\hat y_n=\arg\max_k z_{n,k}=\arg\max_k p_{n,k}, mert a softmax rendezéstartó. A döntéshez tartozó konfidencia cn=maxkpn,kc_n=\max_k p_{n,k}, a helyesség pedig an=𝟙[ŷn=yn]a_n=\mathbb 1[\hat y_n=y_n].

Definíció (top-label kalibráció). Legyen (X,Y)(X,Y) a populációs eloszlásból vett pár, Ŷ\hat Y a modell döntése és C=maxkpk(X)C=\max_kp_k(X) a konfidenciája. A modell top-label kalibrált, ha

P(Y=Ŷ|C=c)=cP\bigl(Y=\hat Y\,\big|\,C=c\bigr)=c

minden c∈[0,1]c\in[0,1]-re (a CC eloszlása szerint majdnem mindenütt).

Definíció (osztályonkénti kalibráció). A modell a kk osztályra kalibrált, ha P(Y=k|pk(X)=c)=cP\bigl(Y=k\,\big|\,p_k(X)=c\bigr)=c minden cc-re. Ez más és erősebb állítás: a „0,9 valószínűséggel vertical” mondat a vertical osztályra vonatkozik. Top-label kalibráció mellett az egyes osztályok külön-külön lehetnek kalibrálatlanok.

Mindkettő populációs, feltételes valószínűségi tulajdonság. Véges mintán még egy tökéletesen kalibrált modellnél sem kell a megfigyelt gyakoriságnak pontosan egyeznie a konfidenciával, és a feltételt folytonos cc-re közvetlenül nem is lehet mérni. Ezért binelt diagnosztikát használunk: a [0,1][0,1] intervallumot B1,…,BMB_1,\ldots,B_M diszjunkt binekre osztjuk, és binenként összevetjük az empirikus pontosságot és az átlagos konfidenciát:

1|Bm|∑n:cn∈Bmanvs.1|Bm|∑n:cn∈Bmcn,\frac{1}{|B_m|}\sum_{n:c_n\in B_m} a_n\quad\text{vs.}\quad\frac{1}{|B_m|}\sum_{n:c_n\in B_m} c_n,

ahol a nevezőben a bin elemszáma áll, és az üres bineket kihagyjuk. Ez a reliability diagram alapja. A binenkénti eltérés becslés: kis binben nagy a mintavételi szórása, a binelés pedig egy binen belül elrejtheti az ellentétes irányú eltéréseket (az egyik részen túl-, a másikon alulbiztos modell binátlaga lehet pontos). A binenkénti egyezés ezért nem a kalibráció definíciója, csak annak zajos, nem elégséges jele.

Log loss. A többosztályos negatív log-likelihood, más néven log loss:

Llog=−1N∑n=0N−1logpn,yn.L_{\log}=-\frac1N\sum_{n=0}^{N-1}\log p_{n,y_n}.

A [D07] szerint ez éppen a PyTorch CrossEntropyLoss default reduction="mean" viselkedése, ha a bemenet a logitmátrix és a cél az int64 osztályindex. A log loss a teljes valószínűségvektort bünteti, ezért a kalibrációt is méri: ha a modell magabiztosan téved, a büntetés nagy.

Brier-pontszám (többosztályos). Legyen Y∈{0,1}N×KY\in\{0,1\}^{N\times K} a one-hot célmátrix. A többosztályos Brier-pontszám

BS=1N∑n=0N−1∑k=0K−1(pn,k−Yn,k)2.\mathrm{BS}=\frac1N\sum_{n=0}^{N-1}\sum_{k=0}^{K-1}\left(p_{n,k}-Y_{n,k}\right)^2.

A tökéletes modellnél BS=0\mathrm{BS}=0; a legrosszabb lehetséges érték 22, mert ha a modell egyetlen rossz osztályra ad 1 valószínűséget, akkor (1−0)2+(0−1)2=2(1-0)^2+(0-1)^2=2. (A bináris esetre a scikit-learn brier_score_loss a [0,1][0,1] értékkészletet dokumentálja; a [D15] oldal tartalmát a fejezet írásakor még nem olvastuk végig, ezért a fenti többosztályos általánosítást saját definícióként adjuk meg, és a kimondott határokat levezetésként ellenőrizzük.)

Reliability diagram és ECE. A binelt konfidencia–pontosság párokat diagramon ábrázoljuk: minden binhez az átlagos konfidencia és a megfigyelt pontosság tartozik. Az expected calibration error a top-label kalibrációs eltérés binelt, mintavételi bizonytalansággal terhelt becslése:

ECE=∑m=1M|{n:cn∈Bm}|N|1|Bm|∑n:cn∈Bmcn−1|Bm|∑n:cn∈Bman|.\mathrm{ECE}=\sum_{m=1}^{M}\frac{|\{n:c_n\in B_m\}|}{N}\left|\frac{1}{|B_m|}\sum_{n:c_n\in B_m}c_n-\frac{1}{|B_m|}\sum_{n:c_n\in B_m}a_n\right|.

A fenti képletekben a biteket például [0,0.2),[0.2,0.4),…,[0.8,1.0][0,0.2),[0.2,0.4),\ldots,[0.8,1.0] módon vehetjük fel. A binek száma és határai a mérési protokoll részei; más binelés más ECE-t ad.

Döntési küszöb és költség. Bináris vagy multilabel esetben a döntési szabály ŷ=𝟙[p≥τ]\hat y=\mathbb 1[p\ge\tau]. A τ\tau küszöböt gyakran költségmátrixszal indokoljuk. Ha a téves pozitív költsége CFPC_{FP}, a téves negatívé CFNC_{FN}, a helyes döntéseké 0, akkor az 1-osztály választásának várható költsége (1−p)CFP(1-p)C_{FP}, a 0-osztályé pCFNpC_{FN}. Az 1-es döntés optimális, ha

(1−p)CFP≤pCFN⇔p≥CFPCFP+CFN,(1-p)C_{FP}\le pC_{FN}\quad\Longleftrightarrow\quad p\ge\frac{C_{FP}}{C_{FP}+C_{FN}},

tehát az optimális küszöb τ*=CFP/(CFP+CFN)\tau^*=C_{FP}/(C_{FP}+C_{FN}). Ez a levezetés feltételezi, hogy a pp értéke kalibrált valószínűség; ha a modell nem kalibrált, akkor a költségküszöb nem az elvárt gyakoriságot adja.

23.2.3 3. Levezetés: skalár hőmérséklet a logitokban és validációs illesztés

A temperature scaling a logitokat egyetlen pozitív skalárral osztja, majd softmaxot számol. A hőmérséklettel skálázott valószínűség:

pi(T)=exp(zi/T)∑j=0K−1exp(zj/T),T>0.p_i(T)=\frac{\exp(z_i/T)}{\sum_{j=0}^{K-1}\exp(z_j/T)},\qquad T>0.

Lemma (a hőmérséklet hatása). Legyen z∈ℝKz\in\mathbb R^K véges logitvektor, p(T)p(T) a fenti eloszlás. Ekkor:

  1. A p(T)p(T) rendezése minden T>0T>0-ra azonos: zi>zjz_i>z_j pontosan akkor, ha pi(T)>pj(T)p_i(T)>p_j(T).
  2. limT→∞pi(T)=1/K\lim_{T\to\infty}p_i(T)=1/K minden ii-re.
  3. Ha zi*=maxjzjz_{i^*}=\max_j z_j egyértelmű maximum, akkor limT→0+pi*(T)=1\lim_{T\to0^+}p_{i^*}(T)=1 és pi(T)→0p_i(T)\to0 minden i≠i*i\ne i^*-ra. Ha rr darab maximális logit van, akkor a maximális osztályok mindegyikének határértéke 1/r1/r, a többié 0.

Bizonyítás. Az 1. állításhoz: T>0T>0 miatt a zi/Tz_i/T leképezés szigorúan rendezéstartó, és az exponenciális függvény is szigorúan monoton; a pozitív normalizáló konstans nem változtat a sorrenden.

A 2. állításhoz: ziz_i véges, ezért T→∞T\to\infty esetén zi/T→0z_i/T\to0, így exp(zi/T)→1\exp(z_i/T)\to1 minden ii-re, tehát

limT→∞pi(T)=1∑j=0K−11=1K.\lim_{T\to\infty}p_i(T)=\frac{1}{\sum_{j=0}^{K-1}1}=\frac1K.

A 3. állításhoz legyen m=maxjzjm=\max_j z_j, és írjuk át:

pi(T)=exp((zi−m)/T)∑j=0K−1exp((zj−m)/T).p_i(T)=\frac{\exp((z_i-m)/T)}{\sum_{j=0}^{K-1}\exp((z_j-m)/T)}.

Ha zi<mz_i<m, akkor zi−m<0z_i-m<0, ezért (zi−m)/T→−∞(z_i-m)/T\to-\infty és exp((zi−m)/T)→0\exp((z_i-m)/T)\to0. Ha zi=mz_i=m, akkor a kitevő azonosan 0, tehát exp(0)=1\exp(0)=1. Így a nevező határértéke az mm értékű osztályok száma, rr, a számláló pedig 1 a maximális, 0 a nem maximális osztályokra. Ebből a harmadik állítás következik. ▫\square

A T=0T=0 tehát kívül esik a paramétertartományon; a T→0+T\to0^+ határérték a kemény argmax-eloszlás. A T=1T=1 az identitás, T<1T<1 élesíti, T>1T>1 lapítja az eloszlást.

A validációs illesztés. A modell súlyait rögzítjük, és csak a TT skalárt hangoljuk a validációs halmazon a log loss minimalizálásával. Legyen a validációs logitmátrix Zval∈ℝNval×KZ^{val}\in\mathbb R^{N_{val}\times K} és a cél yvaly^{val}. A célfüggvény

Lval(T)=−1Nval∑n=0Nval−1logpn,ynval(T),T>0.L_{val}(T)=-\frac1{N_{val}}\sum_{n=0}^{N_{val}-1}\log p_{n,y_n^{val}}(T),\qquad T>0.

A optimalizálást a TT szerinti gradienssel is elvégezhetjük. Egyetlen mintára Ln(T)=−logpy(T)L_n(T)=-\log p_y(T), ahol py(T)=exp(zy/T)/Z(T)p_y(T)=\exp(z_y/T)/Z(T) és Z(T)=∑jexp(zj/T)Z(T)=\sum_j\exp(z_j/T). A logaritmus deriváltja:

∂∂Tlogpy(T)=∂∂T(zyT−logZ(T))=−zyT2−1Z(T)∑jexp(zj/T)(−zjT2)=∑jpj(T)zj−zyT2.\frac{\partial}{\partial T}\log p_y(T)=\frac{\partial}{\partial T}\left(\frac{z_y}{T}-\log Z(T)\right)=-\frac{z_y}{T^2}-\frac{1}{Z(T)}\sum_j\exp(z_j/T)\left(-\frac{z_j}{T^2}\right)=\frac{\sum_j p_j(T)z_j-z_y}{T^2}.

A negatív előjel miatt a batchra átlagolt gradiens

∂Lval∂T=1Nval∑n=0Nval−1zn,yn−∑jpn,j(T)zn,jT2.\frac{\partial L_{val}}{\partial T}=\frac1{N_{val}}\sum_{n=0}^{N_{val}-1}\frac{z_{n,y_n}-\sum_j p_{n,j}(T)z_{n,j}}{T^2}.

A gradiens T>0T>0-n folytonos, de ebből nem következik numerikus stabilitás: T→0+T\to0^+ esetén a 1/T21/T^2 tényező nagy lehet. A gyakorlatban a CrossEntropyLoss logitsbemenetét használjuk, és a pozitivitás biztosítására kereshetünk u=logTu=\log T paraméteren vagy korlátozott, pozitív rácson. A levezetés alakellenőrzése: LL skalár, a gradiens is skalár; a jobb oldal minden tagja logit mértékegységű, osztva T2T^2-tel, tehát TT inverz dimenziójú, ahogy vártuk.

Oktatási kiindulópontként egy kis rács, például T∈{0.25,0.5,0.75,1.0,1.25,1.5,2.0}T\in\{0.25,0.5,0.75,1.0,1.25,1.5,2.0\} használható, de a rács nem garantálja az optimum pontos megtalálását; a keresés semmilyen modellparamétert nem érint. A választott T*T^* nem változtatja az argmax-döntést, tehát az accuracy, a confusion matrix és a belőle számolt macro/micro metrikák változatlanok maradnak. Amit a hőmérséklet megváltoztat, az a log loss, a Brier-pontszám, az ECE és minden küszöb-alapú döntés konfidenciaértéke.

Heurisztika, nem tétel. A temperature scaling modern konvolúciós hálókon gyakran csökkenti az ECE-t, de ez empirikus megfigyelés, nem bizonyított garancia minden modellosztályra. A validációs optimum kiválasztása maga is mintavételi bizonytalanságnak kitett; a [S02] módszertani oldal az intervallumok feltételes, ismételt mintavételi értelmezését hangsúlyozza, ezért a mért ECE-csökkenést a validációs elemszám ismeretében, nem pedig egyetlen pontbecslésként kell kezelni.

23.2.4 4. Eredeti kézi példa és minimális kód

Három minta, K=3K=3, célok y=[0,1,1]y=[0,1,1], logitok:

z(0)=[2.0,0.5,−0.5],z(1)=[0.2,1.8,−0.3],z(2)=[2.5,1.8,0.2].z^{(0)}=[2.0,0.5,-0.5],\quad z^{(1)}=[0.2,1.8,-0.3],\quad z^{(2)}=[2.5,1.8,0.2].

A T=1T=1 softmaxok rendre:

p(0)≈[0.766,0.171,0.063],p(1)≈[0.152,0.756,0.092],p(2)≈[0.626,0.311,0.063].p^{(0)}\approx[0.766,0.171,0.063],\quad p^{(1)}\approx[0.152,0.756,0.092],\quad p^{(2)}\approx[0.626,0.311,0.063].

A log loss értékei: −log0.766≈0.267-\log0.766\approx0.267, −log0.756≈0.280-\log0.756\approx0.280, −log0.311≈1.168-\log0.311\approx1.168, az átlag Lval(1)≈0.572L_{val}(1)\approx0.572. A harmadik minta magabiztos tévedés: a modell a 0 osztályt adja, pedig a cél 1.

Most T=0.5T=0.5: z(2)/T=[5.0,3.6,0.4]z^{(2)}/T=[5.0,3.6,0.4], így p(2)≈[0.795,0.196,0.008]p^{(2)}\approx[0.795,0.196,0.008], és a harmadik minta vesztesége −log0.196≈1.630-\log0.196\approx1.630. Az első két mintán a loss javul (közel 0.0540.054 és 0.0540.054), de az átlag Lval(0.5)≈(0.054+0.054+1.630)/3≈0.579L_{val}(0.5)\approx(0.054+0.054+1.630)/3\approx0.579, tehát a rácsban a T=1T=1 jobb, mert a téves minta túlzott élesítése drágább. Ez a kézi számpélda mutatja, hogy a kalibráló optimum nem automatikusan a legkisebb hőmérséklet.

Minimális ellenőrző kód float64 pontossággal:

import numpy as np

Z = np.array([[2.0,0.5,-0.5],[0.2,1.8,-0.3],[2.5,1.8,0.2]], dtype=np.float64)
y = np.array([0,1,1], dtype=np.int64)

def softmax(Z, T):
    U = Z / T
    U = U - U.max(axis=1, keepdims=True)  # stabil logiteltolás
    E = np.exp(U)
    return E / E.sum(axis=1, keepdims=True)

for T in [0.5, 1.0, 2.0]:
    P = softmax(Z, T)
    loss = -np.mean(np.log(P[np.arange(len(y)), y]))
    print(f"T={T:3.1f}  loss={loss:.6f}  P[2]={P[2].round(3)}")
# Várt kimenet (a fenti kézi számításból):
# T=0.5  loss=0.579231  P[2]=[0.796 0.196 0.008]
# T=1.0  loss=0.571774  P[2]=[0.626 0.311 0.063]
# T=2.0  loss=0.735268  P[2]=[0.495 0.349 0.157]

A kód nem állítja, hogy futtattuk a kéziratban; az értékek a fenti kézi számításból származnak, ezért # Várt kimenet jelölést kaptak.

23.2.5 5. Labor: validációs kalibrációs terv és érintetlen teszt

A labor a GlyphLab adatszerződésére épül. A protokoll rögzített, a teszt csak a legvégén, egyszer kerül kiértékelésre.

  1. Betöltjük a 20.4. V. ellenőrző pont: indokolt CNN-választás és a 24.4. VI. ellenőrző pont: megbízható CNN-training alfejezet szerint tanított CNN state_dict-jét és a GlyphLab metadata.csv split oszlopát.
  2. A validációs 60 képre eval módban logitokat számolunk; a képeken nincs augmentáció, a preprocessing azonos a tanításival.
  3. A TT rácsot [0.5,0.75,1.0,1.25,1.5,2.0][0.5,0.75,1.0,1.25,1.5,2.0] módon állítjuk be, és minden TT-re kiszámítjuk a validációs log losst a Zval/TZ^{val}/T logitokon.
  4. Kiválasztjuk T*T^*-ot, amely a validációs log losst minimalizálja.
  5. Csak ezután számolunk teszt logitokat, és T*T^*-gal kiértékeljük a teszt log losst, Brier-pontszámot, ECE-t és accuracy-t.
# futtatási parancs: python n090_lab.py
import numpy as np
import torch
import csv

torch.manual_seed(20261020)
device = torch.device("cpu")
dtype = torch.float32

# A modellt a n080/n096-ból saját state_dict-ből töltjük; a betöltés helye projektfüggő.
# model = load_trained_model()
# model.load_state_dict(torch.load("model.pt", map_location=device))
# model.to(device).eval()

images = np.load("data/images.npy").astype(np.float32)   # (360,1,24,24)
labels = np.load("data/labels.npy").astype(np.int64)     # (360,)
with open("data/metadata.csv", newline="", encoding="utf-8") as f:
    metadata = list(csv.DictReader(f))
val_idx = np.array([int(r["index"]) for r in metadata if r["split"] == "val"])
test_idx = np.array([int(r["index"]) for r in metadata if r["split"] == "test"])
assert len(val_idx) == len(test_idx) == 60

def gather_logits(model, X, batch=32):
    model.eval()
    outs = []
    with torch.no_grad():
        for i in range(0, len(X), batch):
            xb = torch.from_numpy(X[i:i+batch]).to(dtype=torch.float32, device=device)
            outs.append(model(xb).detach().cpu())
    return torch.cat(outs, dim=0)

# Z_val = gather_logits(model, images[val_idx])  # (60,3)
# Z_test = gather_logits(model, images[test_idx])  # (60,3)
# y_val = torch.from_numpy(labels[val_idx])
# y_test = torch.from_numpy(labels[test_idx])

# temperature grid search
def nll_from_logits(Z, y):
    # D07: CrossEntropyLoss logitsot vár, softmax nélkül; int64 cél.
    return torch.nn.functional.cross_entropy(Z, y).item()

# ECE számítása: max softmax konfidencia és argmax accuracy binelése
def ece(Z, y, bins=(0.0,0.2,0.4,0.6,0.8,1.0)):
    p = torch.softmax(Z, dim=1)
    conf, pred = p.max(dim=1)
    acc = (pred == y).float()
    ece_val = 0.0
    for lo, hi in zip(bins[:-1], bins[1:]):
        mask = (conf >= lo) & (conf < hi + (1e-9 if hi == 1.0 else 0.0))
        n = mask.sum().item()
        if n > 0:
            ece_val += (n/len(y)) * abs(conf[mask].mean().item() - acc[mask].mean().item())
    return ece_val

# Példa a kézi 3 mintás adatra; nem GlyphLab-mérés.
Z_example = torch.tensor([[2.0,0.5,-0.5],[0.2,1.8,-0.3],[2.5,1.8,0.2]])
y_example = torch.tensor([0,1,1], dtype=torch.int64)
T_star = min([0.5,1.0,2.0], key=lambda T: nll_from_logits(Z_example/T, y_example))
print(f"T* a példán: {T_star}")  # várt: 1.0 a 4. szakasz számításai alapján
print(f"ECE T=1 példán: {ece(Z_example, y_example):.4f}")  # kézzel várható ~0.22

A labor átadandó eredménye a validációs kalibrációs protokoll és a tesztkiértékelés. A fenti kódban a modellbetöltés és a metaadatokból kiválasztott 60-60 val/test index a GlyphLab splitjét jelöli; a futás e kéziratban nem elvégzett, ezért a nyomtatott értékek a 4. szakasz kézi példájából származó várt kimenetek. A tényleges futtatás után a naplóba rögzítendő a T*T^*, a val és teszt log loss, Brier, ECE és accuracy, valamint a választott binhatárok.

Eredményértelmezés. Ha a teszt log loss T*T^*-gal kisebb, mint T=1T=1-gyel, akkor a hőmérséklet-illesztés a validációról a tesztre általánosult. Ha az ECE is csökken, a kalibráció javult. A kísérleti állítás ezzel még mindig a GlyphLab három osztályára és a konkrét modellre vonatkozik, nem általános CNN-kalibrációs tétel.

23.2.6 6. Feladatok

F1 (fogalmi, nehézség 1). Definiálja a konfidencia-kalibrációt a binek nyelvén. Adjon ellenpéldát arra, hogy egy modell kalibrált, de haszontalan, és arra, hogy egy modell pontos, de nem kalibrált. Adja meg mindkét esetben a logitokat vagy valószínűségeket.

F2 (levezetési, nehézség 2). Legyen z=[2,2,1]z=[2,2,1], K=3K=3. Számítsa ki a p(T)p(T) eloszlást T=1T=1 és T=0.5T=0.5 esetén, és vezesse le a T→0+T\to0^+ határértéket. Igazolja, hogy a rendezés minden T>0T>0-ra változatlan.

F3 (implementációs, nehézség 2). Írjon teljes Python/PyTorch függvényt, amely adott Z∈ℝN×KZ\in\mathbb R^{N\times K} logitmátrixon, y∈{0,…,K−1}Ny\in\{0,\ldots,K-1\}^N célvektoron és TT-rácson visszaadja a legjobb T*T^*-ot a log loss minimalizálásával. A függvény ne használjon külső adatot; a bemeneteket ellenőrizze. Tesztelje a 4. szakasz hárommintás példáján, és adja meg az elvárt T*T^*-ot.

F4 (hibakeresési, nehézség 2). Az alábbi kódrészlet a kalibráló hőmérsékletet a teszt logitokon választja ki:

def bad_temperature(Z_test, y_test):
    best = None
    for T in [0.5, 0.75, 1.0, 1.25, 1.5, 2.0]:
        loss = torch.nn.functional.cross_entropy(Z_test/T, y_test).item()
        if best is None or loss < best[0]:
            best = (loss, T)
    return best[1]

Mi a hiba, mi a következménye a tudományos állításra nézve, és hogyan kell javítani? Visszaellenőrzésként adja meg, melyik halmaznak kell megmaradnia érintetlennek.

F5 (kísérleti/transzfer, nehézség 3). Tervezzen kísérletet annak eldöntésére, hogy a temperature scaling javítja-e egy CNN log lossát egy új, kétosztályos feladaton, ahol a pozitív osztály ritka (prevalencia 10%). Adja meg a protokollt, a baseline-t, a metrikákat, a megfigyelési egységet, a szükséges split-felépítést és a következtetési korlátot. Indokolja, miért nem elég az accuracy, és miért kell a kalibráló halmazt a threshold-választástól is elkülöníteni.

23.2.7 7. Megoldások és indoklás

F1. A top-label kalibráció definíciója a 2. szakaszban szerepel: P(Y=Ŷ∣C=c)=cP(Y=\hat Y\mid C=c)=c; a binelt diagnosztikában ennek jele, hogy a binekben az átlagos konfidencia közel van a megfigyelt pontossághoz. Kalibrált, de haszontalan: háromosztályos feladaton a konstans p=[1/3,1/3,1/3]p=[1/3,1/3,1/3] modell minden mintára. A konfidencia 1/31/3 mindenütt, a pontosság is 1/31/3, tehát kalibrált, de a döntése véletlenszerű. Pontos, de nem kalibrált: kétosztályos, 100 mintás feladaton a modell 90 mintát helyesen osztályoz, de a 90 helyes mintához 0.99 konfidenciát, a 10 téveshez 0.51-et ad. Az accuracy 0.9, de a 0.99 konfidenciájú binben a pontosság 1.0, a 0.51-es binben 0.0; a modell nem kalibrált. A példa szándékosan szélsőséges, hogy a két fogalom elváljon.

F2. z=[2,2,1]z=[2,2,1]. T=1T=1: exp(2)=7.389\exp(2)=7.389, exp(2)=7.389\exp(2)=7.389, exp(1)=2.718\exp(1)=2.718, összeg 17.49617.496, tehát p=[0.422,0.422,0.156]p=[0.422,0.422,0.156]. T=0.5T=0.5: z/T=[4,4,2]z/T=[4,4,2], exp(4)=54.598\exp(4)=54.598 kétszer, exp(2)=7.389\exp(2)=7.389, összeg 116.585116.585, tehát p=[0.468,0.468,0.063]p=[0.468,0.468,0.063]. A rendezés változatlan: a két maximális logitú osztály egyenlő valószínűségű, a harmadik kisebb. A T→0+T\to0^+ határérték: a lemmában szereplő átírással m=2m=2, a két maximális osztály kitevője 00, a harmadiké (1−2)/T→−∞(1-2)/T\to-\infty, így a határeloszlás [1/2,1/2,0][1/2,1/2,0]. A rendezés invarianciája onnan következik, hogy T>0T>0-val osztás és az exponenciális függvény is szigorúan monoton; a normalizáló konstans pozitív.

F3. A függvény PyTorchban:

import torch

def fit_temperature(Z: torch.Tensor, y: torch.Tensor,
                    grid=[0.5, 0.75, 1.0, 1.25, 1.5, 2.0]) -> float:
    if Z.ndim != 2 or y.ndim != 1 or len(Z) != len(y):
        raise ValueError("Z legyen (N,K), y legyen (N,)")
    if torch.any(torch.tensor(grid) <= 0):
        raise ValueError("A hőmérsékletrács elemei legyenek pozitívak")
    Z = Z.to(dtype=torch.float64)
    y = y.to(dtype=torch.int64)
    best_T, best_loss = None, float("inf")
    for T in grid:
        loss = torch.nn.functional.cross_entropy(Z/T, y).item()
        if loss < best_loss:
            best_loss, best_T = loss, T
    return best_T

Z = torch.tensor([[2.0,0.5,-0.5],[0.2,1.8,-0.3],[2.5,1.8,0.2]], dtype=torch.float64)
y = torch.tensor([0,1,1], dtype=torch.int64)
print(fit_temperature(Z, y))  # várt: 1.0, a 4. szakasz kézi számítása alapján

Alakellenőrzés: Z/TZ/T alakja (N,K)(N,K), a célé (N,)(N,); a cross_entropy default mean redukció. A tolerancia a rácsfelbontásból adódik: ha a rács például 0.05 lépésközű, a hiba a hőmérsékletben legfeljebb 0.05. A függvény float64 bemenettel számol, mert a loss értéke kis különbségekre érzékeny.

F4. A hiba: a hőmérsékletet a teszt logitokon választja. A következmény: a teszt már nem érintetlen; a T*T^* kiválasztása a teszt loss minimalizálásával teszt-adatszivárgás, és a jelentett teszt log loss optimistán torzított lesz. A javítás: a TT-rácsot kizárólag a validációs logitokon értékeljük, majd a kiválasztott T*T^*-ot egyszer alkalmazzuk a tesztre. A visszaellenőrzés: a teszt halmaz semmilyen választási lépésben nem vett részt, tehát a teszt loss torzítatlan becslés marad.

F5. Protokoll: rögzített scene-szintű train/val/test split, a pozitív osztály aránya mindegyikben 10%. A modell betanítása után a validációs logitokon T*T^* kiválasztása log loss szerint. Baseline: T=1T=1, azaz kalibrálás nélküli modell. Metrikák: log loss, Brier-pontszám, ECE, valamint a ritka osztályra recall és precision a CFP=1C_{FP}=1, CFN=5C_{FN}=5 költségküszöbbel. Az accuracy a 90%-os prevalencia miatt csak a többségi osztályt tükrözné, ezért önmagában nem elég. Megfigyelési egység: scene, mert a két nézet nem független. A küszöböt a validációtól is el kell különíteni: ha a küszöböt ugyanazon a validáción hangolnánk, mint a TT-t, akkor a két választás kölcsönhatása miatt a teszt következtetés ismét torzulhat; célszerű a validációt két részre bontani, vagy a küszöböt a feladat kiírása előtt, költségarányokból rögzíteni. Korlát: a ritka osztály 10%-os prevalenciája miatt a binelt ECE-ben a magas konfidenciájú bitek elemszáma kicsi, ezért a becslés szórása nagy.

23.2.8 8. Tipikus tévedés, önellenőrzés és visszahívás

Tipikus tévedés: a maximális softmax-valószínűség garantált bizonytalansági vagy OOD-mérték. A softmax normalizálása miatt a pmaxp_{\max} csak a zárt osztályhalmazhoz viszonyított relatív konfidencia. Ha egy olyan mintát adunk a modellnek, amely egyik tanult osztályhoz sem hasonlít, a logitok lehetnek például [0.1,0.0][0.1,0.0]; ekkor a softmax [0.525,0.475][0.525,0.475], tehát a modell 0.525 konfidenciával dönt, noha a minta az eloszláson kívüli. A kalibráció sem oldja meg ezt: a kalibráció azt méri, hogy a tanult eloszláson a 0.525 körüli döntések milyen gyakran helyesek, nem azt, hogy a konkrét minta ismert-e. Az OOD-detektáláshoz külön pontszám, például a logitok energiája vagy egy sűrűségmodell szükséges; a pmaxp_{\max}-ot ilyenként használni hibás.

Önellenőrzés. (1) A hőmérséklet nem változtatja meg az argmax-ot; igaz-e T=0.1T=0.1-re is? Igen, mert T>0T>0. (2) A Brier-pontszám felső határa 2, nem 1; ellenőriztük a rossz osztályra tett 1 valószínűség esetével. (3) A validációs illesztés után a teszt log loss csökkenése akkor megbízható, ha a tesztet sem a T*T^* választására, sem más hiperparaméter-hangolásra nem használtuk.

Visszahívás. A 22.2. Címkemegőrző transzformációk címkemegőrző transzformációk egysége rögzítette, hogy a validációs képeken nem alkalmazhatunk olyan augmentációt, amely megváltoztatná a címkét; ugyanígy a kalibráló halmaznak a teszt eloszlását kell reprezentálnia. A 11.2. nn.Module és paraméterregisztráció a train()/eval() flag jelentését adta meg: a logitgyűjtés alatt a modellnek eval() módban kell lennie, különben a dropout vagy BatchNorm tanítási statisztikája torzítja a kalibráló logitokat. A 19.2. MobileNet és inverted residual inverted residual blokkjának fej-rétege előtt a logitok skálája az utolsó lineáris rétegtől függ; a hőmérséklet-illesztést ezért minden architektúrához külön kell elvégezni, és a TT értéke nem vihető át automatikusan más modellre. Korábbi anyagból a 7.1. Entrópia, cross-entropy és KL entrópia/KL fogalmai adják a log loss proper scoring tulajdonságának hátterét: mivel DKL(padat∥pmodell)=H(padat)+LlogD_{KL}(p_{\text{adat}}\|p_{\text{modell}})=H(p_{\text{adat}})+L_{\log} és a KL nemnegatív, a várható log loss minimalizálója a valódi eloszlás.

23.2.9 Rövid összefoglaló

A logitok softmax-kimenete valószínűségvektor, de a döntési szabály és a kalibráció két külön értékelési réteg. A log loss és a többosztályos Brier-pontszám a teljes eloszlást bünteti; a reliability diagram és az ECE a konfidencia és a megfigyelt pontosság egyezését méri. A temperature scaling egyetlen T>0T>0 skalárral osztja a logitokat, nem változtatja az argmaxot, de élesíti vagy lapítja az eloszlást; a T→∞T\to\infty határ az egyenletes, a T→0+T\to0^+ a kemény max eloszlás. A TT validációs log loss-minimalizálással illeszthető, és a gradiensét explicite levezettük. A döntési küszöb a költségarányból adódóan τ*=CFP/(CFP+CFN)\tau^*=C_{FP}/(C_{FP}+C_{FN}), és csak kalibrált valószínűségek mellett értelmezhető költségoptimumként. A maximális softmax nem OOD-mérték.

23.2.10 Következő alkalmazás

A 23.3. Páros összehasonlítás és csoportszintű intervallum egységben a páros összehasonlítás és a csoportszintű intervallum következik: a GlyphLab scene-szintű függősége miatt a képenkénti konfidenciaintervallum nem elegendő, ezért a két modell vagy két döntési szabály közötti különbséget páros, scene-szintű újramintavétellel becsüljük.

23.2.11 Felhasznált források