25.2 Multilabel és hierarchikus cél

25.2.1 Cél, előismeret és induló kérdés

A 25.1. Teljes képosztályozó adatfolyam egységben egy teljes képosztályozó adatfolyamot építettünk fel: a batch a betöltéstől a háromlogitos kimenetig egyetlen rögzített alakszerződést követett, és a címke egyetlen kölcsönösen kizáró osztályindex volt. Ebben az alfejezetben azt a kérdést vizsgáljuk, mi történik, ha egy képen egyszerre több címke is igaz lehet. Előismeretnek elegendő a 25.1. Teljes képosztályozó adatfolyam alfejezetből a logit, a fej és a címke fogalma, valamint a 21.2. Learning rate és ütemezés alfejezetből a döntési küszöb szerepe. Induló becslés: két független bináris címke esetén hány kimeneti számra van szüksége a modellnek, és ezeknek összege kötelezően 11 kell-e legyen?

25.2.2 Definíciók és intuíció

Legyen a batch mérete NN, a címkék száma KK. A multilabel feladatban minden nn megfigyeléshez egy

Y∈{0,1}N×KY\in\{0,1\}^{N\times K}

célmátrix tartozik, ahol Yn,k=1Y_{n,k}=1 azt jelenti, hogy a kk-adik címke jelen van az nn-edik képen, Yn,k=0Y_{n,k}=0 pedig azt, hogy a megfigyelt annotáció szerint nincs jelen. A modell itt is logitokat ad:

Z∈ℝN×K,Z\in\mathbb R^{N\times K},

tehát ugyanaz a háló és fej használható, mint a többosztályos esetben; a különbség a normalizálásban és a cél értelmezésében van. A többosztályos cél y∈{0,…,K−1}Ny\in\{0,\ldots,K-1\}^N int64 index, és a softmax egyetlen valószínűségvektorrá normalizálja a logitokat. A multilabel célban ezzel szemben minden címke külön Bernoulli-döntés, ezért az elemenkénti szigmoidot használjuk:

P̂(Yn,k=1)=p̂n,k=σ(zn,k)=11+e−zn,k.\hat P(Y_{n,k}=1)=\hat p_{n,k}=\sigma(z_{n,k})=\frac{1}{1+e^{-z_{n,k}}}.

Az nn-edik sor (p̂n,1,…,p̂n,K)(\hat p_{n,1},\ldots,\hat p_{n,K}) elemei nem alkotnak szükségképpen 11 összegű eloszlást: egy képen lehet egyszerre „jármű” és „éjszakai felvétel”, vagy éppen egyik sem. A kölcsönösen kizáró címkék ezzel szemben egy KK oldalú osztályozás kategóriái; ott a softmax az összes logit együttes függvényeként normál. Kétosztályos határesetben a kapcsolat ragadható meg: ha z1=zz_1=z és z2=0z_2=0, akkor

ez1ez1+ez2=ezez+1=σ(z),\frac{e^{z_1}}{e^{z_1}+e^{z_2}}=\frac{e^z}{e^z+1}=\sigma(z),

ezért a bináris osztályozás egyetlen szigmoidja a softmax speciális paraméterezése. Ez nem jelenti azt, hogy két független multilabel szigmoid ugyanaz, mint egy kétosztályos softmax: az utóbbi (p̂,1−p̂)(\hat p,1-\hat p) kényszert ad, az előbbi két tetszőleges [0,1][0,1]-beli számot.

A szigmoid numerikusan stabil alakja:

σ(z)={11+e−z,z≥0,ez1+ez,z<0.\sigma(z)=\begin{cases}\frac{1}{1+e^{-z}},&z\ge 0,\\[2pt]\frac{e^z}{1+e^z},&z<0.\end{cases}

Így mindkét irányban elkerüljük a túl nagy exponenciális értéket.

25.2.3 A multilabel BCE és a megfigyelési maszk

A többosztályos főút a [D07] szerint logit bemenetet és int64 osztályindexet vár a CrossEntropyLoss-ban. A multilabel főút célja a bináris cross-entropy logitokkal, PyTorchban BCEWithLogitsLoss. Vezessük le a célfüggvényt egyetlen (n,k)(n,k) elemre. A Bernoulli-modell likelihoodja:

p(Yn,k=yn,k∣zn,k)=p̂n,kyn,k(1−p̂n,k)1−yn,k,yn,k∈{0,1}.p(Y_{n,k}=y_{n,k}\mid z_{n,k})=\hat p_{n,k}^{\,y_{n,k}}(1-\hat p_{n,k})^{1-y_{n,k}},\qquad y_{n,k}\in\{0,1\}.

A negatív log-likelihood:

−logp(yn,k∣zn,k)=−yn,klogσ(zn,k)−(1−yn,k)log(1−σ(zn,k)).-\log p(y_{n,k}\mid z_{n,k})=-y_{n,k}\log\sigma(z_{n,k})-(1-y_{n,k})\log(1-\sigma(z_{n,k})).

Mivel 1−σ(z)=σ(−z)1-\sigma(z)=\sigma(-z) és logσ(t)=−log(1+e−t)\log\sigma(t)=-\log(1+e^{-t}), az első tag yn,klog(1+e−zn,k)y_{n,k}\log(1+e^{-z_{n,k}}), a második pedig (1−yn,k)log(1+ezn,k)(1-y_{n,k})\log(1+e^{z_{n,k}}). A két eset összevonható:

ℓ(zn,k,yn,k)=log(1+ezn,k)−yn,kzn,k.\ell(z_{n,k},y_{n,k})=\log\!\left(1+e^{z_{n,k}}\right)-y_{n,k}z_{n,k}.

A log(1+ez)\log(1+e^z) függvényt softplus-nak nevezzük; a memóriaigényt és a numerikus túlcsordulást tekintve javasolt stabil megvalósítása softplus(z)=log(1+e−|z|)+max(z,0)\mathrm{softplus}(z)=\log(1+e^{-|z|})+\max(z,0). A gradiens a láncszabályból:

∂ℓ∂zn,k=σ(zn,k)−yn,k.\frac{\partial \ell}{\partial z_{n,k}}=\sigma(z_{n,k})-y_{n,k}.

Ez megegyezik azzal az intuitív szabállyal, hogy pozitív cél mellett a predikciót 11 felé, negatív cél mellett 00 felé húzzuk; a gradiens akkor nulla, ha p̂n,k=yn,k\hat p_{n,k}=y_{n,k}.

Most mondjuk ki a megfigyelt címkék maszkolásának szabályát.

25.2.3.1 Tétel (maszkolt multilabel BCE)

Legyen Z∈ℝN×KZ\in\mathbb R^{N\times K} a logitmátrix, Y∈{0,1}N×KY\in\{0,1\}^{N\times K} a megfigyelt célmátrix, és M∈{0,1}N×KM\in\{0,1\}^{N\times K} a megfigyelési maszk, ahol Mn,k=1M_{n,k}=1 pontosan akkor, ha az (n,k)(n,k) címke annotáltsága ismert, Mn,k=0M_{n,k}=0 pedig ha hiányzik. Tegyük fel, hogy a bemenet feltétele mellett a címkék feltételesen független Bernoulli-változók σ(zn,k)\sigma(z_{n,k}) paraméterrel, és a hiányzási mechanizmus ignorálható: (i) a megfigyeltség valószínűsége a bemenet ismeretében nem függ a nem megfigyelt valódi címkétől, P(Mn,k=1∣xn,Yn,k)=P(Mn,k=1∣xn)P(M_{n,k}=1\mid x_n,Y_{n,k})=P(M_{n,k}=1\mid x_n) (MAR; speciális esete a teljesen véletlen hiányzás, MCAR, ahol a megfigyeltség az xnx_n-től sem függ), és (ii) a hiányzási mechanizmus paraméterei elkülönülnek a modell paramétereitől. Legyen S=∑n,kMn,k>0S=\sum_{n,k}M_{n,k}>0. Ekkor a megfigyelt adatok negatív log-likelihoodjának átlagos értéke

$$L(Z,Y,M)=\frac1S\sum_{n=1}^{N}\sum_{k=1}^{K}M_{n,k}\Bigl[\log\!\bigl(1+e^{z_{n,k}}\bigr)-Y_{n,k}z_{n,k}\Bigr].$$

Üres maszk, azaz S=0S=0 esetén a loss nem definiált; megvalósításban vagy hibát adunk, vagy szerződésszerűen 00-t adunk vissza, de ezt a hívónak dokumentálnia kell.

Bizonyításvázlat, státusz: saját levezetés. A feltételes függetlenség miatt a megfigyelt rész likelihoodja a megfigyelt elemek likelihoodjainak szorzata. Maszkolatlan elemről az adat nem hordoz likelihood-információt, ezért a log-likelihood összegébe nem kerül tag. A negatív log-likelihood átlaga így a fenti összeg 1/S1/S-szerese, ami a BCE elemenkénti definíciójából következik. ◼\blacksquare

Az ignorálhatósági feltétel mellett a megfigyelési mechanizmus tényezője a likelihoodban a modellparaméterektől független konstans, ezért a megfigyelt-adat likelihood maximalizálása a fenti maszkolt loss minimalizálása. A feltétel nem technikai részlet: ha a megfigyeltség magától a valódi címkétől függ (például a pozitív címkéket gyakrabban jegyzik fel), akkor a megfigyelt célok eloszlása torzított (MNAR), és a maszkolt loss sem ad torzítatlan populációs illesztést; ilyenkor a megfigyelési mechanizmust is modellezni kell. A maszkolás tehát elkerüli a hamis negatív kényszert, de önmagában nem garantál torzítatlan becslést.

A tétel gyakorlati tartalma: a hiányzó címke nem kap Y=0Y=0 célértéket, hanem kimarad az összegből. A PyTorch-ban a BCEWithLogitsLoss(reduction='none') adja a tagokat, a maszkkal szorozva és a maszk összegével osztva kapjuk a normalizált loss-t. Fontos, hogy a default reduction='mean' a batch elemek átlagát venné, ami maszkolt elemeknél nem helyes normalizálás; mindig explicitté kell tenni, mit nevezünk egy megfigyelésnek.

25.2.4 Kézi kis példa

Legyen N=2N=2, K=3K=3, és

Z=(−1,50,82,20,2−0,41,1),Y=(101110),M=(111101).Z=\begin{pmatrix}-1{,}5&0{,}8&2{,}2\\0{,}2&-0{,}4&1{,}1\end{pmatrix},\qquad Y=\begin{pmatrix}1&0&1\\1&1&0\end{pmatrix},\qquad M=\begin{pmatrix}1&1&1\\1&0&1\end{pmatrix}.

A második sor középső címkéje tehát hiányzik: M2,2=0M_{2,2}=0, ezért annak Y2,2=1Y_{2,2}=1 értékét nem használjuk célként. A szigmoid értékek: σ(−1,5)≈0,1824\sigma(-1{,}5)\approx 0{,}1824, σ(0,8)≈0,6900\sigma(0{,}8)\approx 0{,}6900, σ(2,2)≈0,9002\sigma(2{,}2)\approx 0{,}9002, σ(0,2)≈0,5498\sigma(0{,}2)\approx 0{,}5498, σ(−0,4)≈0,4013\sigma(-0{,}4)\approx 0{,}4013, σ(1,1)≈0,7503\sigma(1{,}1)\approx 0{,}7503.

Elemenként a softplus(z)−Yz\mathrm{softplus}(z)-Yz képlettel, amely pozitív célra (Y=1Y=1) softplus(−z)\mathrm{softplus}(-z), negatív célra (Y=0Y=0) softplus(z)\mathrm{softplus}(z):

(n,k)(n,k) YY zz BCE-tag
(1,1)(1,1) 1 −1,5-1{,}5 softplus(1,5)=log(1+e1,5)≈1,7014\mathrm{softplus}(1{,}5)=\log(1+e^{1{,}5})\approx 1{,}7014
(1,2)(1,2) 0 0,80{,}8 softplus(0,8)=log(1+e0,8)≈1,1711\mathrm{softplus}(0{,}8)=\log(1+e^{0{,}8})\approx 1{,}1711
(1,3)(1,3) 1 2,22{,}2 softplus(−2,2)=log(1+e−2,2)≈0,1051\mathrm{softplus}(-2{,}2)=\log(1+e^{-2{,}2})\approx 0{,}1051
(2,1)(2,1) 1 0,20{,}2 softplus(−0,2)=log(1+e−0,2)≈0,5981\mathrm{softplus}(-0{,}2)=\log(1+e^{-0{,}2})\approx 0{,}5981
(2,3)(2,3) 0 1,11{,}1 softplus(1,1)=log(1+e1,1)≈1,3873\mathrm{softplus}(1{,}1)=\log(1+e^{1{,}1})\approx 1{,}3873

Az összeg 4,96314{,}9631, a maszk összege S=5S=5, így L≈0,9926L\approx0{,}9926. A legnagyobb tag az (1,1)(1,1) elem: pozitív cél mellett erősen negatív logit, tehát magabiztos téves predikció. Ha tévesen a hiányzó (2,2)(2,2) elemet negatívként vennénk be, a softplus(−0,4)≈0,5130\mathrm{softplus}(-0{,}4)\approx 0{,}5130 tag is beleszámít, és a loss 5,4761/6≈0,91275{,}4761/6\approx0{,}9127 lenne; a különbség kicsinek tűnik, de a gradiens-ellenőrzés megmutatja a torzítást:

∂ℓ(2,2)∂z2,2=σ(−0,4)−Y2,2≈0,4013−0=0,4013,\frac{\partial \ell(2,2)}{\partial z_{2,2}}=\sigma(-0{,}4)-Y_{2,2}\approx 0{,}4013-0=0{,}4013,

holott a maszkolt változatban ehhez az elemhez nulla gradiens tartozik. A modell tehát hamis negatív cél irányába tanulna egy olyan példán, ahol valójában nincs is megfigyelt negatív annotáció.

25.2.5 Megvalósítási ellenőrzés

Az alábbi függvény a PyTorch nélküli, NumPy referenciát adja meg; a laborban ugyanezt a torch.nn.functional.binary_cross_entropy_with_logits függvénnyel ellenőrizzük.

import numpy as np

def stable_sigmoid(z: np.ndarray) -> np.ndarray:
    # float64 bemenet; z >= 0 elágazással a túlcsordulást elkerüljük
    out = np.empty_like(z, dtype=np.float64)
    pos = z >= 0
    e = np.exp(-np.abs(z))
    out[pos] = 1.0 / (1.0 + e[pos])
    out[~pos] = e[~pos] / (1.0 + e[~pos])
    return out

def masked_bce_with_logits(z: np.ndarray, y: np.ndarray, mask: np.ndarray) -> float:
    # z, y, mask alakja (N, K); y értéke 0 vagy 1; mask értéke 0 vagy 1
    z = np.asarray(z, dtype=np.float64)
    y = np.asarray(y, dtype=np.float64)
    mask = np.asarray(mask, dtype=np.float64)
    if z.shape != y.shape or z.shape != mask.shape:
        raise ValueError("Alakegyezés szükséges: (N, K) mindhárom bemenetre.")
    s = mask.sum()
    if s <= 0:
        raise ValueError("Üres maszk: nincs megfigyelt címke.")
    # stabil softplus: log(1 + e^z) = softplus(z)
    softplus = np.logaddexp(0.0, z)
    terms = softplus - y * z
    return float(np.sum(mask * terms) / s)

A függvény a fenti példára 0,99260{,}9926-ot ad (float64-ben 0,9926142920{,}992614292). A PyTorch-oldali ellenőrzés:

import torch

z = torch.tensor([[-1.5, 0.8, 2.2], [0.2, -0.4, 1.1]], dtype=torch.float64)
y = torch.tensor([[1.0, 0.0, 1.0], [1.0, 1.0, 0.0]], dtype=torch.float64)
mask = torch.tensor([[1.0, 1.0, 1.0], [1.0, 0.0, 1.0]], dtype=torch.float64)

terms = torch.nn.functional.binary_cross_entropy_with_logits(
    z, y, reduction='none')
loss = (mask * terms).sum() / mask.sum()
print(loss.item())  # várt: 0.992614..., 1e-4 toleranciával
print(terms)        # tételenként: 1.7014 1.1711 0.1051 / 0.5981 0.9130 (maszkolt, kimarad) 1.3873

25.2.6 Labor: szintetikus multilabel fej és metrika

A labor célja egy kis, CPU-n ellenőrizhető multilabel osztályozó összeállítása. A GlyphLab három kölcsönösen kizáró osztálya erre nem alkalmas, ezért eredeti szintetikus példát használunk: N=96N=96 képhez 12 dimenziós fix mesterséges jellemzőt rendelünk, és K=4K=4 címkét figyelünk meg. A jellemzők nem valós képekből származnak; a labor a fej, a loss és a metrika szerződését vizsgálja, nem a látási teljesítményt.

# munkakönyvtár: lab/
# python n098_multilabel_lab.py
import torch
import torch.nn as nn

torch.manual_seed(20261020)
N, K, D = 96, 4, 12
X = torch.randn(N, D, dtype=torch.float32)          # (96, 12)
W_true = torch.randn(D, K, dtype=torch.float32) * 0.5
logit_true = X @ W_true
prob_true = torch.sigmoid(logit_true)
Y = (prob_true > 0.5).float()                        # (96, 4)
# 30% véletlenszerű hiányzó annotáció
mask = (torch.rand(N, K) > 0.3).float()              # (96, 4)

class MultilabelHead(nn.Module):
    def __init__(self, d: int, k: int):
        super().__init__()
        self.linear = nn.Linear(d, k)

    def forward(self, x):
        return self.linear(x)                        # logitok, nincs sigmoid

model = MultilabelHead(D, K)
opt = torch.optim.SGD(model.parameters(), lr=0.5)

for step in range(20):
    opt.zero_grad()
    z = model(X)                                     # (96, 4)
    terms = torch.nn.functional.binary_cross_entropy_with_logits(
        z, Y, reduction='none')
    loss = (mask * terms).sum() / mask.sum()
    loss.backward()
    opt.step()

with torch.no_grad():
    pred_prob = torch.sigmoid(model(X))
    pred = (pred_prob > 0.5).float()
    obs = mask.bool()
    acc = ((pred[obs] == Y[obs]).float().mean().item())
print(f"loss={loss.item():.6f}")
print(f"maszkolt elemek a predikcióban egyeznek: {acc:.6f}")

Átadandó eredmény. A futtatás után megadjuk a tanítási loss-t, a maszkolt elemekre számított elemszintű accuracy-t, valamint a N×KN\times K alakú predikciós mátrixot. A véletlen seed és a float32 típus rögzíti a futtatás feltételeit. Az itt közölt loss érték nem mért eredmény, hanem a kód definíciója szerint kiszámítandó kimenet; a labor akkor teljes, ha a tanuló maga futtatja, és a loss tagonkénti kézi számítással egyezik 10−510^{-5} relatív tűrésen belül.

A metrikák közül a multilabel feladatban az elemszintű accuracy félrevezető lehet ritka címkéknél, ezért per-címke F1-et is számolunk: minden kk oszlopra a predikció és cél kétdimenziós kontingencia-táblájából precisionk\text{precision}_k és recallk\text{recall}_k, majd az F1 mikro- és makroátlagát. A micro a pozitív példák halmazát összevonva számol globális pontosságot, a macro a KK per-címke F1 egyszerű átlaga; ritka címkékre a kettő eltér.

A küszöb nem a tanult modell része. A BCE a szigmoid logitot tanítja; a 0,50{,}5-nél nagyobb szabály az esetszámok és költségek ismerete nélkül választott alapértelmezés. A 21.2. Learning rate és ütemezés alfejezetben bevezetett elv itt is érvényes: a küszöböt a validációs halmazon, a maszkolt elemeket figyelembe vevő metrika szerint választjuk, és a végleges modellre csak a rögzített küszöbbel számítunk tesztmetrikát.

25.2.7 Hierarchikus célok

A hierarchikus annotációban a címkék egy irányított gráf vagy fa csúcsai, és konzisztenciakényszer áll fenn: ha egy gyermek címke pozitív, akkor a szülője is pozitív. Formálisan legyen G=(V,E)G=(V,E) irányított gráf a KK csúcsú címkehalmazon, és Yn∈{0,1}VY_n\in\{0,1\}^{V} konzisztens, ha minden (u→v)∈E(u\to v)\in E élre Yn,v=1⇒Yn,u=1Y_{n,v}=1\Rightarrow Y_{n,u}=1. Például „jármű” →\to „kétkerekű”, és „kétkerekű” →\to „kerékpár” esetén a „kerékpár” pozitivitása maga után vonja mindkét ős pozitivitását.

A hierachikus kényszer nem változtat a BCE alakegyezésén; a modell továbbra is KK logitot ad. A kényszert két módon kezelhetjük. Az egyik a predikció utáni vetítés: a gyermek predikcióját nem engedjük nagyobbnak az ősénél, amit a gráfon alulról felfelé haladva p̂u←max(p̂u,maxv:(u→v)p̂v)\hat p_u\leftarrow\max(\hat p_u,\max_{v:(u\to v)}\hat p_v) lépéssel végzünk. A másik a cél oldali hierarchikus loss, amely a szülő–gyermek élpárok logitjait is bünteti az inkonzisztenciáért.

A vetítéses szabály heurisztika, nem általános tétel: feltételezi, hogy a modell egyébként jól kalibrált, és a címkefa konzisztens annotációt ír le. Nem állítja, hogy a vetített kimenet optimális az alkalmazási metrikára, és nem pótolja a hiányzó szülő címkék valódi tanítását.

25.2.8 Tipikus tévedés: a nem annotált címke nem negatív címke

A leggyakoribb hiba a multilabel tanításban, hogy a hiányzó annotációt Yn,k=0Y_{n,k}=0-ként töltjük ki. Ellenpélda. Tegyük fel, hogy egy gyűjteményben a „vaku használata” címke csak akkor kap 11-est, ha a fotós feljegyezte; az üres mező azt jelenti, hogy nem tudjuk. Egy éjszakai képen, amelyen valójában vaku volt, a téves negatív cél hatására a BCE gradiens σ(z)−0>0\sigma(z)-0>0, tehát a logitot lefelé húzza, és a recall romlik annak ellenére, hogy az adatban nem volt megfigyelt negatív példa. A maszk ezt az elemet kihagyja a likelihood-összegből: a modell az adott címkére ott nem tanul, mintha az a megfigyelés nem létezne. A nem annotált elem negatívként kezelése tehát nem pusztán pontatlanság, hanem a likelihood-modell hibája, és a tanult döntési küszöböt szisztematikusan torzíthatja. A példa ugyanakkor a maszkolás határát is mutatja: ha a fotósok éppen a vakus képeknél jegyzik fel gyakrabban a címkét, a hiányzás a valódi címkétől függ (MNAR). A maszk ekkor is kiküszöböli a hamis negatív célokat, de a megfigyelt címkék között a pozitívak túlreprezentáltak, így a modell a vaku valószínűségét a populációra felülbecsülheti. Egy egyszerű szimulációban (valódi arány 0,20{,}2; a pozitívak 90%-át, a negatívak 30%-át jegyzik fel) a megfigyelt címkék pozitív aránya 0,4290{,}429, míg MCAR-hiányzásnál 0,20{,}2. Ezt csak a feljegyzési mechanizmus modellezése vagy egy teljesen annotált validációs részminta korrigálhatja.

25.2.9 Önellenőrzés és visszahívás

Ellenőrző kérdések a szakasz után: (1) A ZZ logitmátrix minden eleme a szigmoid után [0,1][0,1]-ben van-e? (2) A maszkolt loss-ban a nevező SS vagy N⋅KN\cdot K? (3) A gradienst a hiányzó elemre tényleg nullának definiáljuk-e? (4) A küszöbátlépés a loss vagy az értékelés része?

Visszahívás a 13.2. Konvolúció és cross-correlation alfejezetből: a cross-correlation és a konvolúció megkülönböztetésénél is az volt a tanulság, hogy a numerikus forma önmagában nem rögzíti a szemantikai szerződést; itt ugyanúgy, a 0/10/1 célforma önmagában nem mondja meg, hogy a nulla negatív vagy hiányzó annotáció-e. A 25.1. Teljes képosztályozó adatfolyam adatfolyamában a logitok alakja N×KN\times K volt; a multilabel ugyanazt a fejet használja, csak a normalizálás és a loss célalakja változik. A 24.2. CPU/GPU profiling és helyes időmérés alfejezetből pedig azt idézzük fel, hogy a metrika futásidejét a threshold sweep során külön kell mérni: a per-címke F1 KK szorosa az elemszintű pontosságnak, és a sweep költsége nem elhanyagolható, ha a modellt nagyméretű adaton értékeljük.

25.2.10 Feladatok

25.2.10.1 F1. Fogalmi (nehézség 1)

Magyarázza el, miért nem ekvivalens a kétcímkés multilabel feladat a kétosztályos multiclass feladattal. Adjon egy 22 logitból álló konkrét zz vektort, amelyre a softmax és a két elemenkénti szigmoid kimenete különböző döntést ad 0,50{,}5-ös küszöb mellett.

25.2.10.2 F2. Levezetési (nehézség 2)

Vezesse le részletesen, hogy a ℓ(z,y)=log(1+ez)−yz\ell(z,y)=\log(1+e^z)-yz cél deriváltja σ(z)−y\sigma(z)-y, és számítsa ki a gradienst a (2,3)(2,3) elemre a kézi példában. Ellenőrizze a maszkolt elem gradiensének definícióját.

25.2.10.3 F3. Implementációs (nehézség 2)

A fent közölt NumPy függvényt egészítse ki egy masked_bce_grad függvénnyel, amely a loss-nak a logitmátrix szerinti gradiensét adja: ∂L∂zn,k=Mn,kS(σ(zn,k)−Yn,k)\frac{\partial L}{\partial z_{n,k}}=\frac{M_{n,k}}{S}(\sigma(z_{n,k})-Y_{n,k}). Futtassa le a kézi példára, és ellenőrizze a PyTorch autograd gradiensével 10−810^{-8} abszolút tűrés mellett.

25.2.10.4 F4. Hibakeresési (nehézség 2)

Az alábbi kódrészlet hibás:

logits = model(images)                        # (N, K)
probs = torch.softmax(logits, dim=1)
loss = torch.nn.functional.binary_cross_entropy(
    probs, targets.float(), reduction='mean')

Melyik két fogalmat keveri a kód? Mi a következménye egy olyan képen, ahol a két címke közül mindkettő pozitív? Javítsa a kódot, és nevezze meg a numerikusan stabil változatot is.

25.2.10.5 F5. Kísérlettervezési/transzfer (nehézség 3)

Tervezzen kísérletet egy olyan adatkészletre, ahol a címkék 20%20\%-a hiányzik, és a hiányzás valószínűsége nagyobb a ritka címkéknél. A feladat ötből három címke együttes előfordulásának detektálása. Adja meg a megfigyelési egységet, a splitet, a baseline-t, a választott metrikát, a küszöbválasztás protokollját és a következtetés korlátját. Magyarázza el, miért nem használható a teszt halmaz a küszöb keresésére.

25.2.11 Megoldások és indoklás

25.2.11.1 F1 megoldás

A kétosztályos multiclass a softmax normalizálással (p̂,1−p̂)(\hat p,1-\hat p) párt ad, tehát a címkék egymást kizárják. A multilabel két szigmoidja két független [0,1][0,1]-beli érték, amelyek összege nincs 11-hez kötve. Legyen z=(0,7;0,7)z=(0{,}7;\,0{,}7). A softmax (e0,72e0,7,e0,72e0,7)=(0,5;0,5)(\frac{e^{0,7}}{2e^{0,7}},\frac{e^{0,7}}{2e^{0,7}})=(0{,}5;\,0{,}5), tehát 0,50{,}5-ös küszöb mellett egyik címkét sem választjuk vagy éppen egy arbitrázs döntésbe kerülünk; a két szigmoid σ(0,7)≈0,668\sigma(0{,}7)\approx 0{,}668 mindkét címkére, tehát mindkettőt jelen levőnek predikáljuk. A softmax elveszi egy második pozitív címke lehetőségét.

25.2.11.2 F2 megoldás

A softplus(z)=log(1+ez)\mathrm{softplus}(z)=\log(1+e^z) deriváltja a láncszabállyal ez1+ez=σ(z)\frac{e^z}{1+e^z}=\sigma(z). Ezért

∂∂z[log(1+ez)−yz]=σ(z)−y.\frac{\partial}{\partial z}\left[\log(1+e^z)-yz\right]=\sigma(z)-y.

A (2,3)(2,3) elemre z2,3=1,1z_{2,3}=1{,}1, y2,3=0y_{2,3}=0, így a gradiens σ(1,1)≈0,7503\sigma(1{,}1)\approx 0{,}7503, ami a fenti tévedés-elemzésben használt pozitív húzás irányát mutatja a negatív cél felé. A maszkolt gradiens definíciója az Mn,kM_{n,k} szorzó: a hiányzó (2,2)(2,2) elemnél M=0M=0, ezért a gradiens komponense nulla, bár a formula σ(−0,4)−1≈−0,5987\sigma(-0{,}4)-1\approx-0{,}5987 lenne, ha azt negatívként kezdenénk tanítani.

25.2.11.3 F3 megoldás

def masked_bce_grad(z, y, mask):
    # z, y, mask alakja (N, K)
    z = np.asarray(z, dtype=np.float64)
    y = np.asarray(y, dtype=np.float64)
    mask = np.asarray(mask, dtype=np.float64)
    s = mask.sum()
    if s <= 0:
        raise ValueError("Üres maszk.")
    return mask * (stable_sigmoid(z) - y) / s

A PyTorch-ellenőrzés:

zt = torch.tensor([[-1.5, 0.8, 2.2], [0.2, -0.4, 1.1]],
                  dtype=torch.float64, requires_grad=True)
yt = torch.tensor([[1.0, 0.0, 1.0], [1.0, 1.0, 0.0]], dtype=torch.float64)
mt = torch.tensor([[1.0, 1.0, 1.0], [1.0, 0.0, 1.0]], dtype=torch.float64)
terms = torch.nn.functional.binary_cross_entropy_with_logits(
    zt, yt, reduction='none')
loss = (mt * terms).sum() / mt.sum()
loss.backward()
print(np.max(np.abs(zt.grad.numpy() -
      masked_bce_grad(zt.detach().numpy(), yt.numpy(), mt.numpy()))))
# 0.0 várt; a numerikus tűrés 1e-8 alatt kell maradjon

Alakellenőrzés: a gradiens mátrix ugyanakkora, mint ZZ, tehát N×KN\times K; a maszk nélküli formula N×KN\times K, a maszkkal szorzás nem változtatja az alakot. Szélsőeset: ha Y=1Y=1 és z→∞z\to\infty, a gradiens 00-hoz tart; ha Y=0Y=0 és z→−∞z\to-\infty, a gradiens 00-hoz tart; a hiányzó maszk elem tartósan nulla.

25.2.11.4 F4 megoldás

A kód a softmaxot és a bináris cross-entropy-t keveri. A softmax a KK logitot egyetlen eloszlássá normalizálja, ezért a két pozitív címkés képen a cél (1,1)(1,1) nem lehet egyszerre teljesíthető: a softmax probabilitások összege 11, a BCE a szigmoid kimenetet várja, és a log-likelihood interpretáció sérül. Ha a két logit egyenlő, a softmax két 0,50{,}5-öt ad, a loss pedig 2log22\log 2 értékű marad a tökéletesen prediktált két pozitív címke ellenére. A javítás: BCEWithLogitsLoss(logits, targets.float(), reduction='mean'), vagy annak reduction='none' változata maszkkal. Ez numerikusan stabil, mert a log-sum-exp trükköt használja a loss belsejében, és nem igényel külön szigmoidot.

25.2.11.5 F5 megoldás

Egy lehetséges terv: a megfigyelési egység a kép, de ha egy jelenetből több nézet van, a független csoport a scene_id; ezt a GlyphLab-szerződés tanította a 25.1. Teljes képosztályozó adatfolyam alfejezetben. A feladat nem a GlyphLab, ezért az átvitelnél a scene-csoportosítást meg kell őrizni. Az adatot train/val/test arányban 60/20/2060/20/20-ra osztjuk a ritka címkék előfordulását rétegezve. Baseline: az empírikus prior, azaz minden címke prevalenciája a train halmazon; az összetett detektálásra az egyesített címkés pozitív arányt mérjük. A modell egy CNN-backbone KK logit fejjel, veszteség maszkolt BCE. A választás metrikája a validációs per-címke F1 makroátlaga, mert ritka címkékre az elemszintű accuracy félrevezető. A küszöböt a validációs halmazon szabályozzuk globálisan és per-címkeként is; a teszt halmazra csak a kiválasztott küszöbbel számolunk, különben a teszt maga is adaptív modellválasztási ciklusba kerül, és az elvárt generalizációs hibánál optimistább becslést ad. A következtetés korlátja: a hiányzási mechanizmus nem igazoltan véletlenszerű, ezért a hiányzó maszk feltételes függetlenségét a kísérlet nem tudja ellenőrizni; az eredmény csak a megfigyelt címkékre érvényes.

25.2.12 Rövid összefoglaló

A multilabel feladat célja Y∈{0,1}N×KY\in\{0,1\}^{N\times K} mátrix, a modell Z∈ℝN×KZ\in\mathbb R^{N\times K} logitokat ad, és minden címke külön Bernoulli-döntés. A szigmoid elemenkénti, a softmax ezzel szemben egyetlen összegű normalizálást végez; a kétosztályos softmax egyetlen szigmoiddá fajul, de két multilabel szigmoid nem ekvivalens vele. A BCE logitokkal az ℓ(z,y)=softplus(z)−yz\ell(z,y)=\mathrm{softplus}(z)-yz tagot minimalizálja, gradiense σ(z)−y\sigma(z)-y. A megfigyelési maszk a hiányzó címkéket kihagyja a likelihood-összegből; az üres maszk definiálatlan. A küszöböt validáción választjuk, nem a BCE része. A hierarchia apa–gyermek konzisztenciát követel, a vetítés heurisztika. A legfontosabb hiba a nem annotált címke negatívként kezelése, amely hamis gradienssel torzítja a modellt.

25.2.13 Következő alkalmazás

A 25.3. Kis adat és feature-alapú baseline egységben a kis adat és a feature-alapú baseline kérdése következik. A multilabel maszk ott is szerepet kap: ha kevés annotált példánk van, a hiányzó címkék kezelése nélkül a baseline pontossága éppen a leggyakoribb hibás célokból tanul, ezért a feature-alapú modell és a CNN összehasonlításakor a maszkot a baseline-nál is explicit módon kell kezelni.

25.2.14 Felhasznált források