29.4 Anomáliapontszám rekonstrukcióból

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

A 29.3. Regularizált latent reprezentáció alfejezetben láttuk, hogy a rekonstrukciós cél önmagában még nem hoz létre szemantikus reprezentációt: kapacitás és regularizáció nélkül az identitáshoz közeli leképezés is elérhető. Ebben az alfejezetben a rekonstrukciót döntési feladatra használjuk: egy modellt kizárólag „normálisnak” tekintett mintákon tanítunk, majd a rekonstrukciós hibát anomáliapontszámként (anomaly score) értelmezzük. A cél nem az, hogy a hibát valószínűségnek nevezzük, hanem az, hogy a küszöbválasztást és a hibaköltséget validációs protokollhoz kössük, és kimondjuk az eljárás érvényességi határait.

Előismeret: a 29.1. Lineáris és nemlineáris autoencoder autoencoder-definíciója, a 29.2. Denoising és korrupciós modell rekonstrukciós és denoising-célja, valamint a 25.4. Nyílt halmaz és ismeretlen input nyílt halmazú döntés gondolata. Nem szükséges haladó statisztikai előismeret.

Induló kérdés. Az autoencoder átlagos tanítási hibája 0,01. Egy új képen ugyanez a modell 0,05 hibát ad. Mekkora a valószínűsége annak, hogy az új kép anomália? Becslés: ebből az egyetlen számból nem határozható meg. A hiba nem valószínűség, és a modell a tanult sémán kívüli inputot is rekonstruálhatja jól, ahogyan a 4. szakasz ellenpéldája mutatja.

29.4.2 2. Rekonstrukciós pontszám és normal training

Legyen egy kép x∈[0,1]C×H×Wx\in[0,1]^{C\times H\times W}, például a GlyphLab szerződésben C=1C=1, H=W=24H=W=24. Az autoencoder egy fθ:ℝC×H×W→ℝC×H×Wf_\theta:\mathbb R^{C\times H\times W}\to\mathbb R^{C\times H\times W} paraméteres függvény, a rekonstrukció x̂=fθ(x)\hat x=f_\theta(x). A pontszám a kép átlagos négyzetes hibája:

s(x;θ)=1CHW∑c=1C∑h=1H∑w=1W(xc,h,w−x̂c,h,w)2. s(x;\theta)=\frac{1}{C H W}\sum_{c=1}^{C}\sum_{h=1}^{H}\sum_{w=1}^{W} \bigl(x_{c,h,w}-\hat x_{c,h,w}\bigr)^2.

Batch esetén az X∈ℝN×C×H×WX\in\mathbb R^{N\times C\times H\times W} bemenethez és X̂=fθ(X)\hat X=f_\theta(X) rekonstrukcióhoz egy s∈[0,∞)Ns\in[0,\infty)^N pontszámvektor tartozik, ahol sis_i a fenti átlag. A továbbiakban az MSE-pontszámot használjuk; bináris bemenetre a BCE-loss 29.2. Denoising és korrupciós modell alfejezetből szintén lehetséges, de akkor a ponthatárok és a küszöbértékek nem cserélhetők fel automatikusan.

Normal training. A tanítóhalmaz Dtr={xi}i=1nD_{\mathrm{tr}}=\{x_i\}_{i=1}^{n}, amelyről feltesszük, hogy a normál működésből származik. Anomáliacímkét a tanítás nem használ. A cél

θ̂∈argminθ1n∑i=1nℓ(xi,fθ(xi))+λR(θ), \hat\theta \in \arg\min_{\theta} \frac1n\sum_{i=1}^{n} \ell\bigl(x_i,f_\theta(x_i)\bigr) + \lambda R(\theta),

ahol RR a 29.3. Regularizált latent reprezentáció alfejezetben bevezetett sparse, contractive vagy más regularizáció, λ≥0\lambda\ge 0. A regularizáció itt nem dísz: a szűk keresztmetszet vagy a büntetőtag akadályozhatja, hogy a modell tetszőleges inputot identikusan visszaadjon. Ez azonban heurisztika, nem bizonyított szeparációs garancia.

Contamination. Két különböző fogalmat ne keverjünk. A tanítási contamination πtr\pi_{\mathrm{tr}} annak aránya, hogy a feltételezett normál tanítóhalmaz valójában anomáliákat is tartalmaz. Ha πtr>0\pi_{\mathrm{tr}}>0, a normal training feltételezése sérül, és a minimalizált cél a nem kívánt mintákra is illesztheti a modellt. Az értékelési contamination πv\pi_v a validációs vagy tesztkeverék anomáliaaránya; ez a küszöbválasztás és a költség becslésének bemenete, nem a modell tanításáé.

29.4.3 3. Küszöbválasztás és hibaköltség

A döntési szabály rögzített τ∈ℝ\tau\in\mathbb R küszöbbel:

aτ(x)={1,s(x;θ)>τ,0,s(x;θ)≤τ, a_\tau(x)= \begin{cases} 1, & s(x;\theta)>\tau,\\ 0, & s(x;\theta)\le\tau, \end{cases}

ahol az 1 címke jelenti az anomáliát. A τ\tau megválasztásához olyan validációs halmaz kell, amelyben ismert y∈{0,1}y\in\{0,1\} címkék vannak. A validációs pontszámokból becsüljük a hamis pozitív és hamis negatív arányt:

FPR̂(τ)=1nv0∑i:yi=0𝟏{si>τ},FNR̂(τ)=1nv1∑i:yi=1𝟏{si≤τ}, \widehat{\mathrm{FPR}}(\tau)=\frac{1}{n_v^{0}}\sum_{i:y_i=0}\mathbf 1\{s_i>\tau\}, \qquad \widehat{\mathrm{FNR}}(\tau)=\frac{1}{n_v^{1}}\sum_{i:y_i=1}\mathbf 1\{s_i\le\tau\},

ahol nv0n_v^{0} és nv1n_v^{1} a normál és anomália minták száma a validációban. Legyen cfn>0c_{\mathrm{fn}}>0 egy kihagyott anomália költsége, cfp>0c_{\mathrm{fp}}>0 egy hamis riasztásé, πv\pi_v pedig az anomáliák validációs aránya. A várható költség becslése

Ĉπ(τ)=πvcfnFNR̂(τ)+(1−πv)cfpFPR̂(τ). \hat C_\pi(\tau)=\pi_v c_{\mathrm{fn}}\widehat{\mathrm{FNR}}(\tau) +(1-\pi_v)c_{\mathrm{fp}}\widehat{\mathrm{FPR}}(\tau).

A küszöböt a validációs pontszámokból álló rács felett választjuk:

τ*∈argminτĈπ(τ). \tau^*\in\arg\min_{\tau}\hat C_\pi(\tau).

Ha a validáció csak normál mintát tartalmaz, a FNR̂\widehat{\mathrm{FNR}} tag nem becsülhető. Ekkor legfeljebb a normál pontszámok (1−α)(1-\alpha)-kvantilisét választhatjuk, ami a hamis riasztási arányt vezérli, de a detektálási képességről nem ad állítást. A küszöböt nem a tanítóhalmaz pontszámaiból választjuk: azok tipikusan alacsonyak, mert a modell látta a mintákat, ezért a tanítási ponthatár optimista becslés lenne.

29.4.4 4. Ellenpélda: alacsony rekonstrukciós hiba ismeretlen mintán

A fejezet levezetési kötelezettsége annak formális megmutatása, hogy a modell ismeretlen mintát is jól rekonstruálhat, tehát az alacsony pontszám nem azonosítja a normál eloszlást. A legegyszerűbb ilyen eset az identikus rekonstrukció.

Lemma 1 (identikus rekonstrukció mint OOD-kudarc). Legyen 𝒳\mathcal X a lehetséges inputok nem üres halmaza, ℱ={fθ:𝒳→𝒳}\mathcal F=\{f_\theta:\mathcal X\to\mathcal X\} egy paraméteres függvénycsalád, és legyen ℓ:𝒳×𝒳→[0,∞)\ell:\mathcal X\times\mathcal X\to[0,\infty) olyan veszteség, amelyre minden x∈𝒳x\in\mathcal X esetén ℓ(x,x)=0\ell(x,x)=0. Tegyük fel, hogy az identitás fid(x)=xf_{\mathrm{id}}(x)=x eleme ℱ\mathcal F-nek. Ekkor bármely Dtr⊂𝒳D_{\mathrm{tr}}\subset\mathcal X tanítóhalmazra létezik olyan θ\theta paraméter, amelyre a tanítási veszteség 00, és minden x∈𝒳x\in\mathcal X — így minden ismeretlen anomáliamintára is — s(x;θ)=0s(x;\theta)=0.

Bizonyítás. Válasszuk a θ\theta paramétert úgy, hogy fθ=fidf_\theta=f_{\mathrm{id}}. Ekkor minden tanítópontra fθ(xi)=xif_\theta(x_i)=x_i, tehát a veszteségtagok mindegyike 00, az empirikus cél 00. Ugyanebből az okból tetszőleges x∈𝒳x\in\mathcal X-re x̂=x\hat x=x, így az MSE-pontszám minden tagja eltűnik, s(x;θ)=0s(x;\theta)=0. A kihagyott anomáliákat a τ>0\tau>0 küszöb mind normálnak osztályozza, tehát a modell semmilyen elválasztást nem végez. ▫\square

A lemma feltétele triviálisnak tűnhet, de az identitás nem puszta elméleti eset: túl nagy látens térrel és linearitással az optimális rekonstrukció könnyen közelítheti. Tekintsünk egy lineáris autoencodert, ahol E∈ℝh×dE\in\mathbb R^{h\times d} az encoder, D∈ℝd×hD\in\mathbb R^{d\times h} a decoder, és h≥dh\ge d. Ha DE=IdDE=I_d, akkor az egész leképezés f(x)=DEx=xf(x)=DE x=x. Ilyen pár létezik, például E=(Id0)E=\begin{pmatrix}I_d\\0\end{pmatrix} és D=(Id0)D=\begin{pmatrix}I_d&0\end{pmatrix}. A normal training tehát elérheti a nulla hibát, miközben az anomáliafelismerő képesség nulla.

Ez az ellenpélda nem jelenti azt, hogy a rekonstrukciós pontszám használhatatlan. Azt jelenti, hogy a használhatóság az architektúra kapacitásán, a regularizáción és a validáción mért elválasztáson múlik; a tanítási hiba nagysága önmagában nem bizonyíték.

29.4.5 5. Kézi példa és ellenőrző kód

Legyen x∈ℝ2x\in\mathbb R^2, E=(10)E=\begin{pmatrix}1&0\end{pmatrix} és D=(10)D=\begin{pmatrix}1\\0\end{pmatrix}. Ekkor

DE=(1000),x̂=DEx=(x10). DE=\begin{pmatrix}1&0\\0&0\end{pmatrix}, \qquad \hat x=DE x=\begin{pmatrix}x_1\\0\end{pmatrix}.

A modell a második koordinátát eldobja. A tanítóhalmaz legyen {(2,0),(4,0),(1,0)}\{(2,0),(4,0),(1,0)\}. Mindhárom tanítópontra x̂=x\hat x=x, tehát s=0s=0. Az (100,0)(100,0) pont messze van a tanító felhőtől, de a rekonstrukciós hibája szintén 00: a pontszám nem a tanítóhalmaztól mért távolság, hanem a modellezett altértől mért távolság. A (0,3)(0,3) pont esetén x̂=(0,0)\hat x=(0,0), tehát

s((0,3))=12(02+32)=4,5. s((0,3))=\frac{1}{2}\bigl(0^2+3^2\bigr)=4{,}5.

Ha viszont E=I2E=I_2 és D=I2D=I_2, akkor mind az öt pontra s=0s=0, beleértve a (0,3)(0,3) pontot is. Ez a Lemma 1 konkrét kétváltozós esete.

# lab/score_hand_check.py
import numpy as np

E = np.array([[1.0, 0.0]])          # (1,2)
D = np.array([[1.0], [0.0]])        # (2,1)
X = np.array([[2, 0], [4, 0], [1, 0], [100, 0], [0, 3]],
             dtype=np.float32)      # (5,2)

Xhat = X @ E.T @ D.T               # (5,1)@(1,2) = (5,2)
s = np.mean((X - Xhat) ** 2, axis=1)
print(s)                            # [0.  0.  0.  0.  4.5]

E2 = np.eye(2, dtype=np.float32)
D2 = np.eye(2, dtype=np.float32)
Xhat2 = X @ E2.T @ D2.T
print(np.mean((X - Xhat2) ** 2, axis=1))  # [0. 0. 0. 0. 0.]

A példa egyszerre tölti be a kézi kontroll és az ellenpélda szerepét. A szélső eset azt is megmutatja, hogy a nullpontszám nem a tanítóeloszlás tagságát igazolja.

29.4.6 6. Labor: jelölt anomáliateszt a GlyphLab adaton

A labor célja egy kis jelölt anomáliateszt, nem valódi csalás- vagy diagnózisállítás. A normál eloszlást a GlyphLab tiszta tanítóképei alkotják; anomáliának a corrupted_test.npy zajos és fényességgradienssel torzított tesztképeit tekintjük. A cél annak eldöntése, hogy a rekonstrukciós pontszám a párosított tesztpárokban a korrupt oldalon nagyobb-e.

Protokoll.

# lab/anomaly_lab.py — futtatás: cd lab && python anomaly_lab.py
import csv
import json
from pathlib import Path

import numpy as np
import torch
import torch.nn as nn

ROOT = Path(".")
SEED = 20261020
torch.manual_seed(SEED)
np.random.seed(SEED)
device = torch.device("cpu")
dtype = torch.float32

images = np.load(ROOT / "data" / "images.npy")            # (360,1,24,24)
corrupted = np.load(ROOT / "data" / "corrupted_test.npy") # (60,1,24,24)
with (ROOT / "data" / "metadata.csv").open() as f:
    meta = list(csv.DictReader(f))

def idx(split):
    return np.array([int(r["index"]) for r in meta if r["split"] == split])

Xtr = images[idx("train")]      # (240,1,24,24)
Xva = images[idx("val")]        # (60,1,24,24)
Xte = images[idx("test")]       # (60,1,24,24)
assert Xtr.shape == (240, 1, 24, 24)
assert corrupted.shape == (60, 1, 24, 24)

# Validációs szintetikus anomália; ez NEM a corrupted_test, és csak
# a küszöbválasztáshoz használható.
rng = np.random.default_rng(SEED + 1)
Xva_anom = np.clip(Xva + 0.35 * rng.standard_normal(Xva.shape).astype(np.float32),
                   0.0, 1.0)

class ConvAE(nn.Module):
    def __init__(self):
        super().__init__()
        self.enc = nn.Sequential(
            nn.Conv2d(1, 8, 3, stride=2, padding=1), nn.ReLU(),
            nn.Conv2d(8, 16, 3, stride=2, padding=1), nn.ReLU(),
            nn.Flatten(), nn.Linear(576, 32))
        self.dec = nn.Sequential(
            nn.Linear(32, 576), nn.ReLU(),
            nn.Unflatten(1, (16, 6, 6)),
            nn.ConvTranspose2d(16, 8, 3, stride=2, padding=1, output_padding=1),
            nn.ReLU(),
            nn.ConvTranspose2d(8, 1, 3, stride=2, padding=1, output_padding=1),
            nn.Sigmoid())

    def forward(self, x):
        return self.dec(self.enc(x))

model = ConvAE().to(device)
opt = torch.optim.Adam(model.parameters(), lr=1e-3)
lossf = nn.MSELoss()

Xtr_t = torch.from_numpy(Xtr).to(device, dtype)
for epoch in range(30):
    model.train()
    perm = torch.randperm(Xtr_t.shape[0])
    for i in range(0, Xtr_t.shape[0], 32):
        xb = Xtr_t[perm[i:i + 32]]
        opt.zero_grad()
        loss = lossf(model(xb), xb)
        loss.backward()
        opt.step()

def score(model, x_np):
    model.eval()
    with torch.no_grad():
        x = torch.from_numpy(x_np).to(device, dtype)
        y = model(x)
        return torch.mean((x - y) ** 2, dim=(1, 2, 3)).cpu().numpy()

s_va_n = score(model, Xva)
s_va_a = score(model, Xva_anom)
c_fn, c_fp, pi = 3.0, 1.0, 0.5
best_tau, best_cost = None, float("inf")
for tau in np.quantile(np.r_[s_va_n, s_va_a], np.linspace(0.05, 0.95, 191)):
    fp = np.mean(s_va_n > tau)
    fn = np.mean(s_va_a <= tau)
    cost = pi * c_fn * fn + (1.0 - pi) * c_fp * fp
    if cost < best_cost:
        best_cost, best_tau = cost, float(tau)

s_te = score(model, Xte)
s_co = score(model, corrupted)          # a betöltéskori név: corrupted
tn = int(np.sum(s_te <= best_tau))
fp = int(np.sum(s_te > best_tau))
fn = int(np.sum(s_co <= best_tau))
tp = int(np.sum(s_co > best_tau))
paired = float(np.mean(s_co > s_te))

def auc_pairs(neg, pos):
    """ROC AUC Mann–Whitney-alakban: P(pos > neg) + 0,5 · P(pos = neg).

    Minden (negatív, pozitív) párt összevet, ezért a holtversenyt helyesen
    kezeli, és az osztálydarabszámokat a bemenetből veszi."""
    pos = np.asarray(pos)[:, None]
    neg = np.asarray(neg)[None, :]
    return float(np.mean((pos > neg) + 0.5 * (pos == neg)))

assert auc_pairs(np.zeros(4), np.zeros(3)) == 0.5          # minden pontszám azonos
assert auc_pairs([0.0, 0.1], [0.2, 0.3]) == 1.0            # tökéletes rangsor
assert auc_pairs([0.2, 0.3], [0.0, 0.1]) == 0.0            # fordított rangsor
auc = auc_pairs(s_te, s_co)

import datetime, platform, uuid
report = {
    "run_id": uuid.uuid4().hex,
    "created_utc": datetime.datetime.now(datetime.timezone.utc).isoformat(timespec="seconds"),
    "status": "completed",                 # a program ténylegesen lefutott
    "config": {"seed": SEED, "epochs": 30, "batch": 32, "lr": 1e-3, "device": str(device),
               "dtype": str(dtype), "c_fn": c_fn, "c_fp": c_fp, "pi": pi,
               "torch": torch.__version__, "numpy": np.__version__,
               "python": platform.python_version()},
    "threshold": best_tau,
    "val_cost": best_cost,
    "test_confusion": {"TN": tn, "FP": fp, "FN": fn, "TP": tp},
    "paired_win_rate": paired,
    "auc": auc,
}
Path("results").mkdir(exist_ok=True)
(Path("results") / "anomaly_report.json").write_text(json.dumps(report, indent=2))
print(json.dumps(report, indent=2))

Futási jegyzőkönyv. A fenti szkript a mellékelt laborcsomag eredeti GlyphLab-adatán, CPU-n (Python 3.12.3, NumPy 2.3.5, PyTorch 2.14.1+cpu) lefutott; két egymás utáni futás azonos számokat adott. A riport mérési része (a run_id, az időpont és a config futásonként, illetve környezetenként változik):

{
  "status": "completed",
  "threshold": 0.04370777867734401,
  "val_cost": 0.0,
  "test_confusion": {"TN": 60, "FP": 0, "FN": 30, "TP": 30},
  "paired_win_rate": 1.0,
  "auc": 1.0
}

Más verziójú NumPy/PyTorch vagy más CPU mellett a küszöb utolsó jegyei eltérhetnek; a saját futás riportját kell leadni, nem ezt a számsort.

Értelmezés. A két rangsoroló mutató tökéletes: mind a 60 párban a korrupt kép pontszáma a nagyobb (paired_win_rate 1,0), és az AUC is 1,0, tehát létezik olyan küszöb, amely a két tesztcsoportot hibátlanul szétválasztja. A validáción választott küszöb mégis 30 korrupt képet normálisnak minősít (FN = 30). Ennek oka, hogy a validációs szintetikus anomália (0,350{,}35 szórású zaj) sokkal könnyebben felismerhető, mint a teszt korrupciója: a validációs költség 00, így a kvantilisrács már egy alacsony küszöbnél optimumot ér el, amely a valódi tesztkorrupció felére nem elég érzékeny. A tanulság kettős. Egyrészt a küszöb minősége a validációs anomália reprezentativitásán múlik, nem a rangsor minőségén. Másrészt az AUC és a páros nyerési arány küszöbfüggetlen, a confusion matrix viszont egy konkrét döntési szabályt értékel; a kettőt külön kell jelenteni. A val_cost a validációs szintetikus anomáliákra érvényes; a tesztelt korrupt minták is szintetikusak, ezért ez nem valódi csalás- vagy hibadetektálási állítás. A páros összehasonlítás azért fontos, mert a tiszta teszt és a korrupt teszt ugyanazon scene_id/view_id párokat tartalmazza.

29.4.7 7. Feladatok

F1 (fogalmi, nehézség 1). Definiáld a rekonstrukciós pontszámot, a normal traininget, a contaminatiót és a küszöböt. Magyarázd el egy-egy mondatban, miért nem valószínűség a pontszám. Elvárt átadandó: legfeljebb tíz mondatos, saját szavas definíció, egy explicit ellenpélda-utalással.

F2 (levezetési, nehézség 2). Bizonyítsd be a Lemma 1-et a saját szavaiddal. Mutasd meg a d=2d=2, h=3h=3 overcomplete lineáris esetben, hogy a DE=I2DE=I_2 választás minden inputra nulla pontszámot ad. Elvárt átadandó: a bizonyítás lépései, a DD és EE konkrét tömbjei, és a szorzat ellenőrzése.

F3 (implementációs, nehézség 2). Írj olyan NumPy-függvényt, amely egy X∈ℝN×DX\in\mathbb R^{N\times D} batch minden sorára kiszámítja az 1D∑j(Xij−X̂ij)2\frac1D\sum_j(X_{ij}-\hat X_{ij})^2 pontszámot, és reduction='mean' jellegű csapdát ne kövess el. Teszteld: X=(1000)X=\begin{pmatrix}1&0\\0&0\end{pmatrix}, X̂=(2000)\hat X=\begin{pmatrix}2&0\\0&0\end{pmatrix} esetén az eredmény [0,5;0][0{,}5;\ 0], mert az első sor hibája ((1−2)2+02)/2=0,5((1-2)^2+0^2)/2=0{,}5 (a koordinátánkénti átlag; az 11 a négyzetösszeg lenne). Elvárt: futtatható kód, import, két pontra pontos output, float64 típus.

F4 (hibakeresési, nehézség 2). Az alábbi kódrészlet a pontszámot a batch összes elemének átlagaként számítja ki, majd ugyanezt a skalárt használja minden mintához. Mi a hiba, mi a következménye a küszöbválasztásra, és hogyan javítanád? Elvárt: ok, következmény, javított két-két sor, egy assert-tel ellenőrzött visszateszt.

s = np.mean((X - Xhat) ** 2)          # hiba: egyetlen skalár
scores = np.full(X.shape[0], s)       # minden mintára ugyanaz

F5 (kísérleti/transzfer, nehézség 3). Tervezz kísérletet annak eldöntésére, hogy a GlyphLab tiszta vertical képein tanult autoencoder pontszáma elválasztja-e a horizontal és diagonal mintákat a vertical mintáktól. Add meg a protokollt, a baseline-t, a splitet, a metrikát és a következtetési korlátot. Elvárt átadandó: legalább fél oldalas terv, nyitott eredménnyel; előre megadott győztes nem fogadható el.

29.4.8 8. Megoldások és indoklás

F1. A pontszám s(x;θ)=1CHW∑c,h,w(xc,h,w−x̂c,h,w)2s(x;\theta)=\frac1{CHW}\sum_{c,h,w}(x_{c,h,w}-\hat x_{c,h,w})^2. A normal training kizárólag normál feltételezésű mintákon minimalizálja a rekonstrukciós veszteséget. A contamination egy halmaz anomáliaaránya; tanítási és értékelési változatát külön kell kezelni. A küszöb τ\tau olyan szám, amelynél nagyobb pontszám anomáliadöntést ad. A pontszám azért nem valószínűség, mert nem [0,1][0,1]-be eső normalizált mérték, és az identikus rekonstrukció esetén ismeretlen mintára is nulla lehet.

F2. A Lemma 1 bizonyítása: ha ℱ\mathcal F tartalmazza az identitást, az identitás paramétere minden tanítópontra x̂i=xi\hat x_i=x_i, tehát a veszteség 00. Ugyanez tetszőleges új xx-re, tehát az MSE-tagok mindegyike 00, és s(x)=0s(x)=0. A d=2d=2, h=3h=3 esetben például

E=(100100),D=(100010). E=\begin{pmatrix}1&0\\0&1\\0&0\end{pmatrix},\qquad D=\begin{pmatrix}1&0&0\\0&1&0\end{pmatrix}.

Ekkor DE=I2DE=I_2, tehát f(x)=xf(x)=x minden xx-re, és a pontszám azonosan nulla. Alakellenőrzés: E∈ℝ3×2E\in\mathbb R^{3\times 2}, D∈ℝ2×3D\in\mathbb R^{2\times 3}, a szorzat 2×22\times2-es egységmátrix.

F3.

import numpy as np

def per_sample_mse(X, Xhat):
    X = np.asarray(X, dtype=np.float64)
    Xhat = np.asarray(Xhat, dtype=np.float64)
    assert X.shape == Xhat.shape
    assert X.ndim == 2
    return np.mean((X - Xhat) ** 2, axis=1)

X = np.array([[1.0, 0.0], [0.0, 0.0]])
Xhat = np.array([[2.0, 0.0], [0.0, 0.0]])
out = per_sample_mse(X, Xhat)
assert np.allclose(out, [0.5, 0.0], atol=1e-15)
print(out)  # [0.5 0. ]

A mean csak az 1. tengelyre redukál, ezért minden megfigyelésnek külön pontszáma marad.

F4. A hiba a redukciós tengely elhagyása. A np.mean mind a N⋅DN\cdot D elem átlagát adja, így egyetlen skalár jön létre; a minták közötti különbség eltűnik, és a küszöb sem képes az egyedeket szétválogatni. Javítás: tartsuk meg a mintatengelyt, axis=1, illetve tensornál dim=(1,2,3) a NCHW-átlaghoz. Visszateszt:

s = np.mean((X - Xhat) ** 2, axis=1)
assert s.shape == (X.shape[0],)

F5. Minta. Kérdés: a rekonstrukciós pontszám elválasztja-e a nem látott orientációkat a normál vertical mintáktól? Adat: GlyphLab train 80 vertical kép a modellhez, validáció a vertical val 20 kép plusz horizontal/diagonal val 40 kép, teszt a maradék független jelenetek 20 vertical és 40 más orientációjú képe. Baseline legyen a véletlen küszöb vagy a teljes normal osztályozó, metrika a pontszám AUC-értéke csupán a tesztjeleneteken. Protokoll: a modell csak train vertical képeken tanul, a tesztet a küszöbválasztás után értékeljük. Korlát: a GlyphLab szintetikus, tehát az eredmény nem természetes kép-anomáliáról szól; az orientációk különbözősége nem feltétlenül valódi hibamód.

29.4.9 9. Tipikus tévedés, önellenőrzés és visszahívás

A leggyakoribb tévedés, hogy a rekonstrukciós hiba általános anomália-valószínűség. Ez két irányban is hibás. Az 5. szakaszban a (100,0)(100,0) pont a tanítófelhőtől távol van, mégis nulla pontszámot kapott, tehát a kis hiba nem jelent normál tagságot. A nagy hiba sem jelent feltétlenül anomáliát: egy ritka, de a normál eloszlásból származó minta is lehet rosszul rekonstruálható, ha a modell szűk kapacitású. A döntési szabály 1{s>τ}1\{s>\tau\} nem ad P(anomália∣x)P(\text{anomália}\mid x) értéket; ilyen állításhoz likelihood-arány, prior és kalibrált modell kellene.

Önellenőrzés. Ha a validációs normál pontszámok 95%-os kvantilise 0,02, akkor egy 0,021 pontszámú minta biztosan anomália? Nem, ez a küszöb a hamis pozitív arányt vezérli, nem a pontszám jelentését.

Visszahívás. A 28.4. VII. ellenőrző pont: CNN alkalmazási szerződés alkalmazási szerződése itt is érvényes: a cél anomáliadöntés, a target a validációban és teszten bináris címke, a tanító cél rekonstrukció, az output egy pontszám, a metrika FPR/FNR/AUC vagy páros arány, a split scene-szintű, és az inference-szerződés rögzített τ\tau mellett zajlik. A 17.4. Architektúra összehasonlítása kontrollált keretben fair-comparison elve szerint az identikus és a rendesen regularizált autoencoder összevetésekor a kapacitást, a tanítási iterációt és a küszöbválasztási protokollt előre rögzíteni kell, különben az identitás kudarca nem a regularizáció hatását méri.

29.4.10 Rövid összefoglaló

A rekonstrukciós pontszám egy minta és rekonstrukciója közötti átlagos négyzetes hiba, amelyet normal traininggel tanított autoencoder ad. A küszöböt validációs halmazon, ismert anomáliacímkékkel, a hamis pozitív és hamis negatív arányok költséggel súlyozott összege alapján választjuk. A Lemma 1 megmutatja, hogy az identikus leképezés minden ismeretlen mintát nulla hibával rekonstruálhat, tehát a pontszám nem anomália-valószínűség és nem ad önmagában szeparációs garanciát. A labor párosított tiszta-korrupt GlyphLab teszten futtatott, run_id-vel és konfigurációval azonosított jelentést készít; a kimenet nem valódi diagnózis. A gyakorlatban a kapacitás, a regularizáció és a validációs korlát együtt határozza meg az eljárás érvényességét.

29.4.11 Következő alkalmazás

A 30.1. Pretext és downstream feladat a rekonstrukciót pretext feladatként használja tovább: az encoder itt tanult reprezentációja downstream osztályozás bemenete lehet, és a fejezetben bevezetjük az önfelügyelt kiértékelés alapfogalmait.

29.4.12 Felhasznált források