13.2 Konvolúció és cross-correlation

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

A 13.1. Kép mint diszkrét többcsatornás jel egységben a képet a 𝒢(H,W)={0,…,H−1}×{0,…,W−1}\mathcal G(H,W)=\{0,\ldots,H-1\}\times\{0,\ldots,W-1\} rácson definiált diszkrét jelként rögzítettük. Ebben az alfejezetben egyetlen szürkeárnyalatos képet vizsgálunk, tehát X∈ℝH×WX\in\mathbb R^{H\times W} mátrixot; a batch- és csatornaindexeket most rögzített, nem változó dimenzióknak tekintjük, és az általános N×Cin×H×WN\times C_{in}\times H\times W alak csak a 14.2. Több bemeneti és kimeneti csatorna egységben kerül elő.

Előismeret: a 13.1. Kép mint diszkrét többcsatornás jel rácspont-, pixel- és NCHW-fogalma, valamint az 1.2. Szakmailag megalapozott modellezési állítások állítástípus-osztályozása. Az induló kérdés: ha a torch.nn.Conv2d nevében a „convolution” szó szerepel, akkor valóban matematikai konvolúciót számol-e? A válasz nemmel kezdődik, és ennek a nemleges válasznak a pontos tartalma adja az egység gerincét.

13.2.2 Definíció és intuíció

Kernel. A kernel (szűrőmag, filter kernel) egy kis, kh×kwk_h\times k_w méretű valós súlymátrix:

K∈ℝkh×kw.K\in\mathbb R^{k_h\times k_w}.

A kernel minden (a,b)(a,b) pozícióhoz egy skalár súlyt rendel; a gyakorlatban kh=kw=3k_h=k_w=3 vagy 55 gyakori, de az alábbi definíciók páratlan méretet nem követelnek meg. A kernel nem kép, hanem egy lokális súlyozási minta: a bemeneti kép minden pozíciójában ugyanazt a khkwk_h k_w darab súlyt használjuk.

Valid cross-correlation. Rögzítsünk egy H×WH\times W bemenetet és egy kh≤Hk_h\le H, kw≤Wk_w\le W kernelt. A KK kernellel vett, valid tartományú cross-correlation a következő Yxc∈ℝ(H−kh+1)×(W−kw+1)Y^{xc}\in\mathbb R^{(H-k_h+1)\times(W-k_w+1)} kimenetet adja:

Yi,jxc=(K⋆X)i,j=∑a=0kh−1∑b=0kw−1Ka,bXi+a,j+b,Y^{xc}_{i,j}=(K\star X)_{i,j}=\sum_{a=0}^{k_h-1}\sum_{b=0}^{k_w-1}K_{a,b}\,X_{i+a,\,j+b},

ahol 0≤i≤H−kh0\le i\le H-k_h és 0≤j≤W−kw0\le j\le W-k_w. A kernel bal felső sarka mindig az input (i,j)(i,j) rácspontjához igazodik; onnan az a,ba,b indexek jobbra és lefelé futnak. A valid szó azt jelenti, hogy a kernel teljes egészében az input belsejében marad, tehát nem lép ki a kép határán, és nincs szükség peremfeltételezésre.

Matematikai konvolúció. Ugyanezen a bemeneten és kernelen a diszkrét, valid tartományú matematikai konvolúció definíciója az indexkonvenciónkban:

Yi,jcv=(K*X)i,j=∑a=0kh−1∑b=0kw−1Ka,bXi+kh−1−a,j+kw−1−b.Y^{cv}_{i,j}=(K\ast X)_{i,j}=\sum_{a=0}^{k_h-1}\sum_{b=0}^{k_w-1}K_{a,b}\,X_{i+k_h-1-a,\,j+k_w-1-b}.

A különbség a bemeneti index irányában van: a kernel 180 fokkal el van forgatva a bemenethez képest. A kernel 180 fokos elforgatását külön operátorral rögzítjük:

R(K)a,b=Kkh−1−a,kw−1−b,0≤a<kh,0≤b<kw.R(K)_{a,b}=K_{k_h-1-a,\,k_w-1-b},\qquad 0\le a<k_h,\ 0\le b<k_w.

A 2×22\times2-es kernelre például RR felcseréli a sorokat és az oszlopokat is: R(w00w01w10w11)=(w11w10w01w00)R\begin{pmatrix}w_{00}&w_{01}\\ w_{10}&w_{11}\end{pmatrix}=\begin{pmatrix}w_{11}&w_{10}\\ w_{01}&w_{00}\end{pmatrix}.

Boundary, valid és padding. A fenti képletek a legegyszerűbb határkezelést testesítik meg: a kernel nem lép ki a képből, és minden olyan pozíciót kihagyunk, ahol a kernel túllógna. Ezt nevezzük valid módnak. A gyakorlati rétegek gyakran nullákkal töltik ki a képet a határon (zero padding): ha mind a négy oldalon ph,pwp_h,p_w sornyi ill. oszlopnyi nullát adunk hozzá, akkor a kiterjesztett input X̃∈ℝ(H+2ph)×(W+2pw)\tilde X\in\mathbb R^{(H+2p_h)\times(W+2p_w)}, és a valid cross-correlation kimeneti mérete

Hout=H+2ph−kh+1,Wout=W+2pw−kw+1.H_{out}=H+2p_h-k_h+1,\qquad W_{out}=W+2p_w-k_w+1.

Az általános stride- és dilationfüggő képlet a 14.1. Stride, padding, dilation és outputméret egységben következik; itt mindenhol stride 11 és dilation 11 érvényes.

Bias. A konvolúciós rétegekben minden kimeneti csatornához egyetlen b∈ℝb\in\mathbb R skalár tartozik, amelyet a cross-correlation eredményének minden térbeli elemére rögzített konstansként hozzáadunk:

Yi,jbias=(K⋆X)i,j+b.Y^{\mathrm{bias}}_{i,j}=(K\star X)_{i,j}+b.

A bb tehát nem függ sem a bemenettől, sem a térbeli pozíciótól. A bias nélküli cross-correlation lineáris leképezés: αX+βZ\alpha X+\beta Z bemenethez α(K⋆X)+β(K⋆Z)\alpha(K\star X)+\beta(K\star Z) tartozik. A bias hozzáadása affin leképezést eredményez; a lineáris és affin megkülönböztetés ugyanaz, mint a 3.2. Mátrixszorzás és affín réteg affin rétegében: lineáris leképezés a nullát nullába viszi, a biasos affin leképezés általában nem.

13.2.3 A két operátor kapcsolata: tétel és bizonyítás

A gyakorlati könyvtárak dokumentációjának olvasásához szükséges állítást explicit tételként mondjuk ki.

Tétel (valid cross-correlation és konvolúció kapcsolata). Legyen X∈ℝH×WX\in\mathbb R^{H\times W}, K∈ℝkh×kwK\in\mathbb R^{k_h\times k_w}, kh≤Hk_h\le H, kw≤Wk_w\le W, és legyen RR a 180 fokos kernelforgatás a fenti definíció szerint. Ekkor minden érvényes (i,j)(i,j) kimeneti indexre

(K*X)i,j=(R(K)⋆X)i,j.(K\ast X)_{i,j}=\big(R(K)\star X\big)_{i,j}.

Bizonyítás. A matematikai konvolúció definícióját írjuk fel, majd hajtsunk végre indexcserét. Legyen a′=kh−1−aa'=k_h-1-a és b′=kw−1−bb'=k_w-1-b. Az (a,b)↦(a′,b′)(a,b)\mapsto(a',b') leképezés bijekció a {0,…,kh−1}×{0,…,kw−1}\{0,\ldots,k_h-1\}\times\{0,\ldots,k_w-1\} halmazon, ezért véges összegben az indexek átnevezése nem változtatja az összeg értékét:

(K*X)i,j=∑a=0kh−1∑b=0kw−1Ka,bXi+kh−1−a,j+kw−1−b(K\ast X)_{i,j}=\sum_{a=0}^{k_h-1}\sum_{b=0}^{k_w-1}K_{a,b}\,X_{i+k_h-1-a,\,j+k_w-1-b}

=∑a′=0kh−1∑b′=0kw−1Kkh−1−a′,kw−1−b′Xi+a′,j+b′=\sum_{a'=0}^{k_h-1}\sum_{b'=0}^{k_w-1}K_{k_h-1-a',\,k_w-1-b'}\,X_{i+a',\,j+b'}

=∑a′=0kh−1∑b′=0kw−1R(K)a′,b′Xi+a′,j+b′=(R(K)⋆X)i,j.=\sum_{a'=0}^{k_h-1}\sum_{b'=0}^{k_w-1}R(K)_{a',b'}\,X_{i+a',\,j+b'}=\big(R(K)\star X\big)_{i,j}.

A második egyenlőség az indexcserét, a harmadik a RR definícióját használja; a negyedik a cross-correlation definíciójából adódik. A kimeneti indexhalmaz mindkét oldalon azonos, mert a kernel mérete nem változott.

A tétel fordított iránya ugyanígy bizonyítható, és a F2 feladatban kérjük is. A tartalmi tanulság: a matematikai konvolúció nem más, mint a 180 fokkal elforgatott kernellel vett cross-correlation. A különbség tehát a kernel indexsorrendjében van, nem a bemenetben vagy a kimeneti rácsban.

Következmény. Ha R(K)=KR(K)=K, azaz a kernel 180 fokos forgásszimmetrikus, akkor a cross-correlation és a konvolúció ugyanazt a numerikus eredményt adja minden bemenetre. Az aszimmetrikus kernel a két operátort megkülönbözteti.

13.2.4 A PyTorch Conv2d definíció szerinti viselkedése

A [D10] hivatalos dokumentáció olvasott szakasza szerint a torch.nn.Conv2d az XX bemenet és a KK súly cross-correlationját számítja, kernelmegfordítás nélkül. A dokumentáció jelölésében a súlyt és bemenetet összekötő ⋆\star a valid 2D cross-correlation operátor; a bias az egyes kimeneti csatornákra adódik hozzá. Ez a megállapítás itt szakirodalmi/definíciós állítás a dokumentáció olvasott szakasza alapján, nem pedig empirikus általánosítás.

Az 1.2. Szakmailag megalapozott modellezési állítások állítástípus-tanulsága itt közvetlenül alkalmazandó: a Conv2d osztály neve nem definíció. Aki a matematikai konvolúciót szeretné PyTorch-ban, annak a kernelt 180 fokban el kell forgatnia, például torch.flip(K, dims=[2,3]) művelettel. A tanult hálózatoknál a két konvenció közötti különbség nem „jó” vagy „rossz”, hanem azt jelenti, hogy ugyanaz a leképezés a megfordított kernel súlyozásával jelenik meg; előre rögzített, nem tanult szűrőknél azonban a különbségtétel numerikus hibához vezethet, ahogy az alábbi kézi példa mutatja.

13.2.5 Eredeti kézi kis példa

Legyen a bemenet a 13.1. Kép mint diszkrét többcsatornás jel stílusában egy 3×33\times3-as, [0,1][0,1]-beli intenzitású kép:

X=(0.20.50.10.80.30.60.40.90.7),K=(10−23).X=\begin{pmatrix}0{.}2&0{.}5&0{.}1\\0{.}8&0{.}3&0{.}6\\0{.}4&0{.}9&0{.}7\end{pmatrix},\qquad K=\begin{pmatrix}1&0\\-2&3\end{pmatrix}.

A kh=kw=2k_h=k_w=2 kernel aszimmetrikus, tehát a két operátor különbözni fog.

Cross-correlation. A K⋆XK\star X mátrix elemei a fenti definícióval:

Tehát

K⋆X=(−0.51.72.70.6).K\star X=\begin{pmatrix}-0.5&1.7\\2.7&0.6\end{pmatrix}.

Matematikai konvolúció. A 180180 fokkal elforgatott kernel

R(K)=(3−201).R(K)=\begin{pmatrix}3&-2\\0&1\end{pmatrix}.

A tétel szerint K*X=R(K)⋆XK\ast X=R(K)\star X, és ennek elemei:

Tehát

K*X=(−0.11.92.70.4).K\ast X=\begin{pmatrix}-0.1&1.9\\2.7&0.4\end{pmatrix}.

A két kimenet közötti különbség az aszimmetrikus kernel megfordításából adódik; az (1,0)(1,0) pozíció értéke véletlenül egybeesik, de a mátrix mégsem azonos. Ha b=0.5b=0.5 biast adunk a cross-correlation réteghez, a kimenet

(−0.51.72.70.6)+0.5(1111)=(0.02.23.21.1).\begin{pmatrix}-0.5&1.7\\2.7&0.6\end{pmatrix}+0.5\begin{pmatrix}1&1\\1&1\end{pmatrix}=\begin{pmatrix}0.0&2.2\\3.2&1.1\end{pmatrix}.

13.2.6 Labor: kézi és NumPy-ellenőrzés

A labor a lab/n050/ munkakönyvtárban fut; a kód a képletekből számított értékeket ellenőrzi, ezért az alábbi várt kimenet a fenti levezetésből származik, nem pedig a szerző által futtatott mérésből. A hallgató feladata a futtatás és a toleranciavizsgálat elvégzése.

# lab/n050/check_convs.py
import numpy as np

X = np.array([[0.2, 0.5, 0.1],
              [0.8, 0.3, 0.6],
              [0.4, 0.9, 0.7]], dtype=np.float32)
K = np.array([[1.0, 0.0],
              [-2.0, 3.0]], dtype=np.float32)

def corr2d_valid(X, K):
    H, W = X.shape
    kh, kw = K.shape
    out = np.zeros((H - kh + 1, W - kw + 1), dtype=np.float32)
    for i in range(H - kh + 1):
        for j in range(W - kw + 1):
            for a in range(kh):
                for b in range(kw):
                    out[i, j] += K[a, b] * X[i + a, j + b]
    return out

def conv2d_valid(X, K):
    return corr2d_valid(X, np.rot90(K, 2))   # 180 fokos forgatás

Yc = corr2d_valid(X, K)
Yf = conv2d_valid(X, K)
print("cross-correlation:\n", Yc)
print("convolution:\n", Yf)
# Várt:
# cross-correlation: [[-0.5  1.7]
#                     [ 2.7  0.6]]
# convolution:       [[-0.1  1.9]
#                     [ 2.7  0.4]]

Futtatási parancs: python lab/n050/check_convs.py. A dtype mindenütt float32, az eszköz CPU; random seedre nincs szükség, mert a függvény determinisztikus, véletlenszám-generátort nem hív.

A PyTorch-oldal ugyanezt az NCHW-indexeléssel ellenőrzi; a 13.1. Kép mint diszkrét többcsatornás jel permutációjának megfelelően az egycsatornás képet (1,1,H,W)(1,1,H,W) tensorré alakítjuk:

import torch
import torch.nn.functional as F

Xt = torch.tensor(X.reshape(1, 1, 3, 3), dtype=torch.float32)
Kt = torch.tensor(K.reshape(1, 1, 2, 2), dtype=torch.float32)

Yc_torch = F.conv2d(Xt, Kt)                     # NCHW, stride=1, padding=0
Kt_flipped = torch.flip(Kt, dims=[2, 3])
Yf_torch = F.conv2d(Xt, Kt_flipped)             # matematikai konvolúció

print("torch Yc:", Yc_torch.squeeze())
print("torch Yf:", Yf_torch.squeeze())

Az ellenőrzés kritériuma: np.allclose(Yc, Yc_torch.numpy(), atol=1e-6) igaz, és np.allclose(Yf, Yf_torch.numpy(), atol=1e-6) igaz. A torch.flip a kernel 180 fokos elforgatását végzi; ez a PyTorch-alakú kernel esetén a kh,kwk_h,k_w dimenziók megfordítását jelenti.

13.2.7 Feladatok

F1 feladat — fogalmi, nehézség 1. Különböztesse meg a valid cross-correlationt és a matematikai konvolúciót. Adjon olyan kernelcsaládot, amelyre a két operátor minden bemenetre azonos, és egy konkrét ellenpéldát, amelyre nem. Átadandó: definíciók, a szimmetria feltétele, egy 2×22\times2-es aszimmetrikus kernel és egy rövid indoklás.

F2 feladat — levezetési/bizonyítási, nehézség 2. Bizonyítsa be, hogy R(R(K))=KR(R(K))=K, majd ezt és a fenti tételt használva mutassa meg, hogy F(R(K),X)=K⋆XF(R(K),X)=K\star X. Átadandó: lépésenkénti levezetés, az indexhalmaz bijektivitásának indoklása és a végeredmény alakellenőrzése.

F3 feladat — implementációs, nehézség 1. Implementálja a corr2d_valid függvényt, és számítsa ki a kimenetet a következő bemenetre és kernelre:

X=(142031253112),K=(2−101).X=\begin{pmatrix}1&4&2\\0&3&1\\2&5&3\\1&1&2\end{pmatrix},\qquad K=\begin{pmatrix}2&-1\\0&1\end{pmatrix}.

Átadandó: kód, a kimeneti mátrix, a kimeneti alak és a belső összegzések indoklása.

F4 feladat — hibakeresési, nehézség 2. Az alábbi függvény a conv2d_valid nevet viseli, de hibás:

def conv2d_valid_bad(X, K):
    H, W = X.shape
    kh, kw = K.shape
    out = np.zeros((H - kh + 1, W - kw + 1))
    for i in range(H - kh + 1):
        for j in range(W - kw + 1):
            out[i, j] = np.sum(K * X[i:i+kh, j:j+kw])
    return out

Az elvárt viselkedés a matematikai konvolúció. Lokalizálja a hibát, indokolja a következményét a fenti X,KX,K példán, javítsa a kódot, és ellenőrizze a javítást a várt numerikus kimenettel. Átadandó: hiba oka, következmény, javított kód, ellenőrző futás eredménye.

F5 feladat — kísérleti/transzfer, nehézség 3. Tervezzen rögzített szűrős kísérletet a GlyphLab data/images.npy képeire: veszik-e észre a vertical és horizontal osztályok közötti különbséget a

K=(−101−101−101)K=\begin{pmatrix}-1&0&1\\-1&0&1\\-1&0&1\end{pmatrix}

előre rögzített élkereső kernel és annak R(K)R(K) elforgatottja különbözőképpen? Adjon protokollt: kérdés, hipotézis, adat, megfigyelési egység, kiszámítandó metrika, baseline és érvényességi korlát. Nem kell előre garantált győztest adni. Átadandó: protokoll szövege, a kimeneti méret számítása 24×24-es inputra, és annak indoklása, miért nem használható a test split a szűrő kiválasztására.

13.2.8 Megoldások és indoklás

F1 megoldás. A cross-correlation definíciója Yi,jxc=∑a,bKa,bXi+a,j+bY^{xc}_{i,j}=\sum_{a,b}K_{a,b}X_{i+a,j+b}, a konvolúcióé Yi,jcv=∑a,bKa,bXi+kh−1−a,j+kw−1−bY^{cv}_{i,j}=\sum_{a,b}K_{a,b}X_{i+k_h-1-a,j+k_w-1-b}. A fenti tétel szerint K*X=R(K)⋆XK\ast X=R(K)\star X; ha R(K)=KR(K)=K, akkor a két kimenet azonos minden XX-re, valid tartományon. A 180 fokos forgásszimmetria feltétele Ka,b=Kkh−1−a,kw−1−bK_{a,b}=K_{k_h-1-a,k_w-1-b} minden (a,b)(a,b)-re; ilyen például

Ksym=(010141010).K_{\mathrm{sym}}=\begin{pmatrix}0&1&0\\1&4&1\\0&1&0\end{pmatrix}.

Ellenpélda a fenti 2×22\times2-es K=(10−23)K=\begin{pmatrix}1&0\\-2&3\end{pmatrix}, mert K0,0=1≠3=K1,1=R(K)0,0K_{0,0}=1\neq 3=K_{1,1}=R(K)_{0,0}, tehát a két operátor kimenete eltér.

F2 megoldás. A RR definícióját kétszer alkalmazva:

R(R(K))a,b=R(K)kh−1−a,kw−1−b=Kkh−1−(kh−1−a),kw−1−(kw−1−b)=Ka,b,R(R(K))_{a,b}=R(K)_{k_h-1-a,k_w-1-b}=K_{k_h-1-(k_h-1-a),\,k_w-1-(k_w-1-b)}=K_{a,b},

tehát R(R(K))=KR(R(K))=K. A tétel szerint minden SS kernelre S*X=R(S)⋆XS\ast X=R(S)\star X; válasszuk az S=R(K)S=R(K) kernelt. Ekkor

F(R(K),X)=R(K)*X=R(R(K))⋆X=K⋆X.F(R(K),X)=R(K)\ast X=R(R(K))\star X=K\star X.

A kimenet mindkét oldalon (H−kh+1)×(W−kw+1)(H-k_h+1)\times(W-k_w+1) alakú, mert a kernel mérete RR alatt változatlan. A bizonyítás az indexcserés levezetés közvetlen alkalmazása; a tétel feltételei (kh≤Hk_h\le H, kw≤Wk_w\le W, valid tartomány) azonosak, tehát a lépés megengedett.

F3 megoldás. A kód a laboréval azonos; a kimenet H=4H=4, W=3W=3, kh=kw=2k_h=k_w=2 esetén (3,2)(3,2) alakú:

Yxc=(172809).Y^{xc}=\begin{pmatrix}1&7\\2&8\\0&9\end{pmatrix}.

Ellenőrzés: a (2,0)(2,0) elem 2X2,0+(−1)X2,1+0X3,0+1X3,1=2⋅2−5+0+1=02X_{2,0}+(-1)X_{2,1}+0X_{3,0}+1X_{3,1}=2\cdot2-5+0+1=0; a (2,1)(2,1) elem 2⋅5−3+0+2=92\cdot5-3+0+2=9. A YY elemei az összegzési definícióból következnek; a shape a valid képletből Hout=4−2+1=3H_{out}=4-2+1=3, Wout=3−2+1=2W_{out}=3-2+1=2.

F4 megoldás. A hiba oka: a függvény a kernel megfordítása nélkül képezi a KK és az inputablak elemenkénti szorzatösszegét, tehát valójában cross-correlationt számol, miközben a neve matematikai konvolúciót ígér. A fenti XX és KK bemeneten a hibás függvény a cross-correlation eredményét adja vissza a konvolúció várt értéke helyett, így az elvárt kimenettől való eltérés a kernel aszimmetriájából származik. A javítás a kernel 180 fokos forgatása a belső ablakozás előtt:

import numpy as np

def conv2d_valid_correct(X, K):
    H, W = X.shape
    kh, kw = K.shape
    K_rot = np.rot90(K, 2)
    out = np.zeros((H - kh + 1, W - kw + 1))
    for i in range(H - kh + 1):
        for j in range(W - kw + 1):
            out[i, j] = np.sum(K_rot * X[i:i+kh, j:j+kw])
    return out

A várt eredmény a 3×33\times3-as példán

K*X=(−0.11.92.70.4),K\ast X=\begin{pmatrix}-0.1&1.9\\2.7&0.4\end{pmatrix},

az ellenőrző np.allclose(conv2d_valid_correct(X, K), expected, atol=1e-6) igaz.

F5 megoldás. Protokoll:

  1. Kérdés: elválasztja-e a rögzített vertical élkereső kernel és annak 180 fokos forgatottja a vertical és horizontal osztályokat a GlyphLab képeken?
  2. Hipotézis: KK átlagos kimeneti energiája nagyobb a vertical, R(K)R(K)-é a horizontal osztályon; a diagonal osztályon a különbség iránya nem garantált.
  3. Adat: data/images.npy NCHW float32, data/labels.npy int64; a képtensor indexelését a 13.1. Kép mint diszkrét többcsatornás jel rögzítette.
  4. Megfigyelési egység: kép; a csoportosítás miatt a scene_id figyelembe veendő, de ez a leíró elemzésben nem okoz split-átszivárgást, ha csak a train részt használjuk.
  5. Split: kizárólag train és szükség esetén val a leíró megfigyelésre; a test a későbbi modellválasztás után marad zárva.
  6. Metrika: minden képre E(X)=∑i,j((K⋆X)i,j)2E(X)=\sum_{i,j}\big((K\star X)_{i,j}\big)^2, ahol a 24×2424\times24-es inputra a valid kimenet 22×2222\times22; osztályonkénti átlag és 95%-os, scene-szintű bootstrap intervallum az 5.3.–5.4. gondolatmenetével.
  7. Változó tényező: kernel mint KK vagy R(K)R(K).
  8. Értékelés: osztályonkénti energiaátlagok leíró összevetése; a torch-nem-tanuló, rögzített szűrő nem választható ki a testen.

A kimeneti méret: Hout=24−3+1=22H_{out}=24-3+1=22, tehát a valid kimenet 22×2222\times22. Az energia a negatív értékek négyzetre emelésével nem veszíti el az iránykiértékelést a négyzetes aggregáció szintjén, de az előjeles átlag is használható; a döntést a protokollban rögzíteni kell. A test-értékelés kizárásának oka: ha a szűrőt vagy a küszöböt a testen választanánk, az optimista torzítást vinne a későbbi modellösszehasonlításba, ahogy az 1.2. Szakmailag megalapozott modellezési állítások ellenpéldája is mutatja.

13.2.9 Tipikus tévedés és ellenpélda

A leggyakoribb tévedés: „a torch.nn.Conv2d konvolúciót számol, mert a neve ezt mondja.” Az ellenpélda a fenti X,KX,K pár: a torch.nn.functional.conv2d a K⋆XK\star X mátrixot adja, a matematikai konvolúció viszont K*XK\ast X-et, és a két mátrix különbözik. A D10 dokumentáció ezt a valid 2D cross-correlation kifejezéssel expliciten rögzíti. A tévedés következménye: előre definiált szűrőknél (pl. élkereső kernel) a rossz konvenció rossz numerikus eredményt ad; tanult kerneleknél pedig az értelmezési dokumentáció lesz hibás, mert a megtanult súly a megfordított párjával ekvivalens. A 12.2. Checkpoint és folytathatóság tanulsága itt is érvényes: a checkpointban tárolt state_dict['weight'] önmagában nem mondja meg, melyik operátorkonvencióhoz tartozik; a konvenciót a kódverzióval és a modellkártyával együtt kell nyilvántartani.

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

13.2.11 Rövid összefoglaló

A cross-correlation a kernel bal felső sarkát az input aktuális pozíciójához illesztve, kernelmegfordítás nélkül képez szorzatösszeget; a matematikai konvolúció ugyanezt 180 fokkal elforgatott kernellel végzi. A valid tartományon a két operátor kimeneti mérete azonos, és a kapcsolatuk K*X=R(K)⋆XK\ast X=R(K)\star X, ahol RR a kernel 180 fokos forgatása. A bizonyítás egy indexcserés bijekcióra épül. A PyTorch Conv2d dokumentációja cross-correlationt specifikál; ez előre definiált szűrőknél numerikus különbséget, tanult kerneleknél ekvivalens, de dokumentálandó konvenciót jelent. A labor a 3×3-as példát NumPy- és PyTorch-oldalon egyaránt ellenőrzi.

13.2.12 Következő alkalmazás

A 13.3. Lokális szűrők és tanult reprezentáció ezt a súlyozási műveletet tanult lokális reprezentációként értelmezi: a kernelek mint él-, textúra- és iránydetektorok jelennek meg, és a bias nélküli operátor linearitása a súlymegosztás előnyeinek levezetéséhez ad alapot.

13.2.13 Források