16.1 Eltolási equivariance és invariance

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

Ebben az alfejezetben két, gyakran összekevert fogalmat választunk szét: az eltolási ekvivarianciát (shift equivariance) és az eltolási invarianciát (shift invariance). Az előbbi azt mondja meg, hogyan viselkedik egy operátor kimenete, ha a bemenetet eltoljuk; az utóbbi azt, hogy a kimenet egyáltalán nem változik. A megkülönböztetés nem szóhasználati kérdés: a CNN-rétegek tervezésekor éppen az a cél, hogy a konvolúciós réteg ekvivariáns legyen, a hálózat végén lévő aggregáló rétegek pedig a kívánt mértékű invarianciát hozzák létre.

Előfeltételek: a 13.4. Határkezelés és frekvenciaintuíció egységből a véges képek határkezelése (valid, zero és circular padding), a 14.4. Csoportos és depthwise konvolúció egységből a csatornák közötti kapcsolat korlátozása, a 15.4. Független gradiensellenőrzési protokoll egységből a numerikus ellenőrzés fegyelme. Visszautalunk a 15.1. Súly- és biasgradiens súlymegosztási gondolatára, a 12.1. Tanítás, validáció és kiértékelési mód train/eval megkülönböztetésére és a 4.1. Függvény, határérték és derivált függvényfogalmára.

Induló kérdés: ha egy 24×2424\times 24 pixeles GlyphLab-képet három képponttal jobbra tolunk, akkor egy 3×33\times 3-as szűrő kimeneti térképe is pontosan három képponttal tolódik-e el, és a végső osztályozási logit változatlan marad-e? A válasz első fele feltételek mellett igen, második fele általában nem — ezt a megkülönböztetést dolgozzuk ki.

16.1.2 Az eltolási operátor és a cross-correlation definíciója

A jelölést a 14.2. Több bemeneti és kimeneti csatorna egység NCHW-szerződése szerint rögzítjük, de a levezetéshez a batchindexet elhagyjuk, mert az eltolás csatornánként és képenként függetlenül hat. Legyen a bemeneti kép

X∈ℝCin×H×W.X\in\mathbb R^{C_{in}\times H\times W}.

A kernel K∈ℝCout×Cin×kh×kwK\in\mathbb R^{C_{out}\times C_{in}\times k_h\times k_w}, a bias b∈ℝCoutb\in\mathbb R^{C_{out}}. A használt operátor a PyTorch Conv2d által számolt cross-correlation, kernelmegfordítás nélkül; a 13.2. Konvolúció és cross-correlation egységben rögzítettük, hogy ez nem azonos a matematikai konvolúcióval, de a szimmetriafogalmak szempontjából a kernelmegfordítás egy rögzített transzformáció, ezért az equivariance-állítás mindkét változatra azonos szerkezetű.

Definíció (valid cross-correlation, stride 1, padding 0). A Z=F(X)Z=F(X) kimenet alakja Cout×H′×W′C_{out}\times H'\times W', ahol H′=H−kh+1H'=H-k_h+1, W′=W−kw+1W'=W-k_w+1, és

Zo,i,j=∑c=0Cin−1∑p=0kh−1∑q=0kw−1Ko,c,p,qXc,i+p,j+q+bo,i∈[0,H′−1],j∈[0,W′−1].Z_{o,i,j}=\sum_{c=0}^{C_{in}-1}\sum_{p=0}^{k_h-1}\sum_{q=0}^{k_w-1}K_{o,c,p,q}\,X_{c,i+p,j+q}+b_o, \qquad i\in[0,H'-1],\ j\in[0,W'-1]. \tag{1}

Az egyes kimeneti pozíciókhoz tartozó kh×kwk_h\times k_w méretű bemeneti ablakot recepciós mezőnek nevezzük; a 16.3. Elméleti és effektív recepciós mező egységben ezt általánosabban vizsgáljuk.

Definíció (eltolási operátor). Legyen τ=(τh,τw)∈ℤ2\tau=(\tau_h,\tau_w)\in\mathbb Z^2. A TτT_\tau operátor a végtelen nulla-kiterjesztésű rácson hat:

(TτX)c,u,v=Xc,u−τh,v−τw,(T_\tau X)_{c,u,v}=X_{c,u-\tau_h,v-\tau_w}, \tag{2}

ahol a definíció szerint az eredeti [0,H−1]×[0,W−1][0,H-1]\times[0,W-1] tartományon kívüli indexekre XX értéke nulla. A véges képek világában ez azt jelenti, hogy a kép tartalma a (τh,τw)(\tau_h,\tau_w) vektorral eltolódik, a felszabaduló sáv pedig nullákkal töltődik fel. Ha τh,τw≥0\tau_h,\tau_w\ge 0, akkor

(TτX):,u,v=X:,u−τh,v−τwha u≥τh,v≥τw,(T_\tau X)_{:,u,v}=X_{:,u-\tau_h,v-\tau_w}\quad\text{ha }u\ge\tau_h,\ v\ge\tau_w,

és nulla egyébként. A kép mérete változatlan marad. Más eltolási változatok — crop, circular — a laborban szerepelnek; ezek más operátort definiálnak, és az equivariance-állítás határfeltételei eltérnek.

Az eltolás itt a térbeli indexekre hat, a csatornaindexet nem érinti. A csatornák közötti permutáció egy másik szimmetria lenne, amellyel itt nem foglalkozunk.

16.1.3 Ekvivariancia és invariancia mint operátoregyenlet

Legyen FF egy tetszőleges operátor, amely képeket képekre, vagy képeket skalárokra képez.

Definíció (eltolási ekvivariancia). Az FF operátor eltolási ekvivariáns az eltolások egy 𝒯\mathcal T halmazára nézve, ha minden τ∈𝒯\tau\in\mathcal T esetén

F(TτX)=TτF(X)F(T_\tau X)=T_\tau F(X) \tag{3}

minden olyan XX-re és kimeneti indexre, ahol mindkét oldal értelmezett. A TτT_\tau a kimeneti oldalon a kimeneti rácsnak megfelelő eltolást jelöli; ha a kimeneti rács felbontása eltér, ezt külön rögzíteni kell.

Az egyenlet szemléletes jelentése: a szűrő alkalmazása és az eltolás felcserélhető. Ha előbb eltolom a képet, majd szűröm, ugyanazt kapom, mintha előbb szűrném, majd a kimeneti térképet tolnám el.

Definíció (eltolási invariancia). Az FF operátor eltolási invariáns az eltolások 𝒯\mathcal T halmazára nézve, ha minden τ∈𝒯\tau\in\mathcal T esetén

F(TτX)=F(X).F(T_\tau X)=F(X). \tag{4}

Itt a kimenet nem változik meg az eltolás hatására. Tipikus példa a globális átlagolás: ha a kép minden pixelét átlagoljuk, az eltolás a nulla-paddingelt határon kívül nem változtatja az átlagot.

A két egyenlet összevetése mutatja a lényegi különbséget: a (3) egyenletben a jobb oldalon TτT_\tau még mindig hat a kimenetre, vagyis az eltolás megőrződik a kimenetben; a (4) egyenletben a kimenetből eltűnik az eltolás. Az ekvivariancia tehát nem gyengébb invariancia, hanem más tulajdonság: az egyik megtartja, a másik eltünteti az eltolást.

A két fogalom metszete nem üres: a nulla leképezés F(X)=0F(X)=0 egyszerre invariáns (F(TτX)=0=F(X)F(T_\tau X)=0=F(X)) és ekvivariáns (F(TτX)=0=Tτ0=TτF(X)F(T_\tau X)=0=T_\tau 0=T_\tau F(X)), ezért egyik tulajdonságot sem választja el a másiktól. Szétválasztó példák: a konstans, de nem nulla kimenet, F(X)=𝟏F(X)=\mathbf 1 (csupa egyes kép), invariáns, de nem ekvivariáns, mert a kimeneti rácson ható nullával kitöltő TτT_\tau a τ≠0\tau\neq0 eltolásnál nullasávot hoz létre, így TτF(X)≠𝟏=F(TτX)T_\tau F(X)\neq\mathbf 1=F(T_\tau X). Az identitásleképezés F(X)=XF(X)=X ekvivariáns, de nem invariáns, mert TτX≠XT_\tau X\neq X általában. Mindkét példában a kimeneti térre ható TτT_\tau ugyanaz a (2) szerinti, nullával kitöltő eltolás. A fogalmi különbséget az F1 feladatban mélyítjük el.

16.1.4 A fő tétel: cross-correlation ekvivarianciája a belső tartományon

A következő állítás az [S01] kurzusjegyzet által is tárgyalt tulajdonság saját, pontos feltételekkel ellátott levezetése.

Tétel (valid cross-correlation eltolási ekvivarianciája a belső tartományon). Legyen FF az (1) képlettel definiált valid cross-correlation, stride s=1s=1, padding ph=pw=0p_h=p_w=0. Legyen τh,τw≥0\tau_h,\tau_w\ge 0 egészek, és tegyük fel, hogy τh≤H−kh\tau_h\le H-k_h és τw≤W−kw\tau_w\le W-k_w. Ekkor minden o∈[0,Cout−1]o\in[0,C_{out}-1] kimeneti csatornára és minden olyan (i,j)(i,j) párra, amelyre

τh≤i≤H−kh,τw≤j≤W−kw,\tau_h\le i\le H-k_h,\qquad \tau_w\le j\le W-k_w,

teljesül

F(TτX)o,i,j=F(X)o,i−τh,j−τw=[TτF(X)]o,i,j,F(T_\tau X)_{o,i,j}=F(X)_{o,i-\tau_h,j-\tau_w}=[T_\tau F(X)]_{o,i,j}, \tag{5}

ahol [TτF(X)]o,i,j=F(X)o,i−τh,j−τw[T_\tau F(X)]_{o,i,j}=F(X)_{o,i-\tau_h,j-\tau_w} a kimeneti rács eltolásának definíciója.

Az (i,j)(i,j)-re vonatkozó feltétel jelöli ki a belső tartományt: az alsó korlát (i≥τhi\ge\tau_h, j≥τwj\ge\tau_w) miatt az eltolt képen a kernelablak nem éri el a bal és a felső nullasávot, a felső korlát (i≤H−khi\le H-k_h) pedig a valid kimenet utolsó indexe, H′−1H'-1. A tartományon kívül két külön határeset van. (a) Ha i<τhi<\tau_h vagy j<τwj<\tau_w, a jobb oldali [TτF(X)]o,i,j[T_\tau F(X)]_{o,i,j} a kimeneti eltolás nullával kitöltött sávjába esik, tehát 00, a bal oldal viszont a részben nullasávra eső ablak összege plusz bob_o; az egyenlőség általában nem áll. (b) A bias ebben a sávban önmagában is sérti az egyenlőséget: csupa nulla XX esetén F(TτX)o,i,j=boF(T_\tau X)_{o,i,j}=b_o, míg [TτF(X)]o,i,j=0[T_\tau F(X)]_{o,i,j}=0, ha bo≠0b_o\neq0. Egydimenziós ellenőrzés: x=(1,2,3)x=(1,2,3), k=(1,1)k=(1,1), b=0b=0, τ=1\tau=1 mellett F(x)=(3,5)F(x)=(3,5), F(Tτx)=F(0,1,2)=(1,3)F(T_\tau x)=F(0,1,2)=(1,3) és TτF(x)=(0,3)T_\tau F(x)=(0,3); az i=0i=0 pont a nullasávban van és sérti az egyenlőséget, az i=1=τi=1=\tau belső pont teljesíti.

Bizonyítás. A bizonyítás a definíciók behelyettesítésén és az összegzés indexeinek átnevezésén alapul. Induljunk ki a bal oldalból, és alkalmazzuk először FF, majd TτT_\tau definícióját:

F(TτX)o,i,j=∑c=0Cin−1∑p=0kh−1∑q=0kw−1Ko,c,p,q(TτX)c,i+p,j+q+bo.F(T_\tau X)_{o,i,j} =\sum_{c=0}^{C_{in}-1}\sum_{p=0}^{k_h-1}\sum_{q=0}^{k_w-1}K_{o,c,p,q}\,(T_\tau X)_{c,i+p,j+q}+b_o.

A (2) definíció szerint (TτX)c,u,v=Xc,u−τh,v−τw(T_\tau X)_{c,u,v}=X_{c,u-\tau_h,v-\tau_w}, tehát

F(TτX)o,i,j=∑c∑p,qKo,c,p,qXc,i+p−τh,j+q−τw+bo.F(T_\tau X)_{o,i,j} =\sum_{c}\sum_{p,q}K_{o,c,p,q}\,X_{c,\,i+p-\tau_h,\,j+q-\tau_w}+b_o. \tag{6}

A feltételből i≤H−khi\le H-k_h, ezért a legnagyobb p=kh−1p=k_h-1 esetén is i+p−τh≤H−1−τh≤H−1i+p-\tau_h\le H-1-\tau_h\le H-1; az i≥τhi\ge\tau_h alsó korlát és p≥0p\ge0 miatt pedig i+p−τh≥0i+p-\tau_h\ge 0. Tehát minden XX-index az eredeti tartományban van, nullával kitöltött elem nem lép fel.

Most írjuk fel F(X)F(X) definícióját az (i−τh,j−τw)(i-\tau_h,\,j-\tau_w) kimeneti pozícióra — a feltételek miatt ez a pozíció értelmezett, hiszen 0≤i−τh≤H−kh−τh≤H′−10\le i-\tau_h\le H-k_h-\tau_h\le H'-1 (és ugyanígy jj-re), ahol H′=H−kh+1H'=H-k_h+1:

F(X)o,i−τh,j−τw=∑c∑p,qKo,c,p,qXc,(i−τh)+p,(j−τw)+q+bo.F(X)_{o,i-\tau_h,j-\tau_w} =\sum_{c}\sum_{p,q}K_{o,c,p,q}\,X_{c,\,(i-\tau_h)+p,\,(j-\tau_w)+q}+b_o. \tag{7}

A (6) és (7) összegek tagonként azonosak, mert a kernel KK független az eltolástól, és az összeadás kommutatív: az i+p−τhi+p-\tau_h és (i−τh)+p(i-\tau_h)+p indexek megegyeznek. A bias bob_o konstans, mindkét oldalon ugyanaz, tehát nem befolyásolja az egyenlőséget. Ezzel

F(TτX)o,i,j=F(X)o,i−τh,j−τw,F(T_\tau X)_{o,i,j}=F(X)_{o,i-\tau_h,j-\tau_w},

ami éppen az (5) állítás. ▫\square

A bizonyításból látszik a kulcsmechanizmus: a kernel súlyai minden pozícióban ugyanazok (weight sharing, 15.1. Súly- és biasgradiens), ezért az eltolás csak az indexeket mozgatja, a súlyokat nem. Ha a súlyok pozíciófüggők lennének, az egyenlőség nem állna fenn — ez az F2 feladatban visszatér.

A tétel csak nemnegatív eltolásra lett kimondva. Negatív τ\tau esetén a belső tartomány feltétele tükröződik: az eltolt kép nullasávja a jobb, illetve az alsó oldalon jelenik meg, és a tartomány 0≤i≤H−kh+τh0\le i\le H-k_h+\tau_h (ugyanígy jj-re). A teljes állítás mindkét irányra hasonló, de a laborban a pozitív eset elegendő.

16.1.5 A stride mint részcsoport-korlátozás

Ha a cross-correlation stride ss-sel dolgozik, a kimeneti rács ss-szeresen ritkább. A kimeneti pozíció (i′,j′)(i',j')-höz a bemeneti ablak (i′s+p,j′s+q)(i's+p,\ j's+q) ponthoz kezdődik. Ha a bemenetet τ=s⋅m=(smh,smw)\tau=s\cdot m=(s m_h, s m_w) vektorral toljuk, ahol m∈ℤ2m\in\mathbb Z^2, akkor

Fs(TsmX)o,i′,j′=Fs(X)o,i′−mh,j′−mw=[TmFs(X)]o,i′,j′,F_s(T_{sm}X)_{o,i',j'} =F_s(X)_{o,i'-m_h,j'-m_w} =[T_m F_s(X)]_{o,i',j'},

a belső tartományon. A levezetés azonos az előző bizonyítással, csak az ii indexet i′si's-re cseréljük. A lényeg: az eltolásoknak az a halmaza, amelyre az ekvivariancia a kimeneti rácson változatlan formában teljesül, a

𝒯s={(smh,smw):mh,mw∈ℤ}\mathcal T_s=\{(s m_h, s m_w): m_h,m_w\in\mathbb Z\}

halmaz. Ez az összes kétdimenziós egész eltolás ℤ2\mathbb Z^2 csoportjának részcsoportja (az összeadásra zárt, az ellentett elemet is tartalmazza). Páratlan, például (1,0)(1,0) eltolás esetén nincs olyan egész mm, amelyre Fs(T(1,0)X)=TmFs(X)F_s(T_{(1,0)}X)=T_m F_s(X) teljesülne a kimeneti rácson, mert a kimeneti rács felbontása nem tud félpixeles eltolást reprezentálni. Ez a stride-részcsoport fogalma: az equivariance csak a rács ritkításának megfelelő részcsoporton áll fenn.

16.1.6 Kézi számpélda a határ feltételére

Legyen H=W=6H=W=6, Cin=Cout=1C_{in}=C_{out}=1, kernel 3×33\times 3, minden eleme Kp,q=1K_{p,q}=1, bias b=0b=0, stride 1, padding 0. A bemenet legyen Xi,j=i⋅6+jX_{i,j}=i\cdot 6+j, azaz

X=(01234567891011121314151617181920212223242526272829303132333435).X=\begin{pmatrix} 0&1&2&3&4&5\\ 6&7&8&9&10&11\\ 12&13&14&15&16&17\\ 18&19&20&21&22&23\\ 24&25&26&27&28&29\\ 30&31&32&33&34&35 \end{pmatrix}.

A valid kimenet 4×44\times 4. Válasszuk az eltolást τ=(1,1)\tau=(1,1)-nek. A nulla-paddingelt eltolt kép TτXT_\tau X sorai:

TτX=(0000000012340678910012131415160181920212202425262728).T_\tau X=\begin{pmatrix} 0&0&0&0&0&0\\ 0&0&1&2&3&4\\ 0&6&7&8&9&10\\ 0&12&13&14&15&16\\ 0&18&19&20&21&22\\ 0&24&25&26&27&28 \end{pmatrix}.

Számítsuk ki a belső tartomány egy pontját. Az F(X)F(X) kimenet 4×44\times 4-es, és a (0,0)(0,0) pozícióhoz tartozó 3×33\times 3 ablak az XX bal felső része:

F(X)0,0=0+1+2+6+7+8+12+13+14=63.F(X)_{0,0}=0+1+2+6+7+8+12+13+14=63.

Az F(TτX)F(T_\tau X) kimenet ugyancsak 4×44\times 4-es, és az (1,1)(1,1) pozícióhoz tartozó ablak a TτXT_\tau X sorai 1–3, oszlopai 1–3:

F(TτX)1,1=0+1+2+6+7+8+12+13+14=63.F(T_\tau X)_{1,1}=0+1+2+6+7+8+12+13+14=63.

Az [TτF(X)]1,1=F(X)0,0=63[T_\tau F(X)]_{1,1}=F(X)_{0,0}=63, tehát az (1,1)(1,1) pozícióban az egyenlőség teljesül. Ez a belső tartomány része: az eltolt képen ez az ablak már teljesen az eredeti XX eltolt tartalmán belül helyezkedik el.

Most nézzük a határpozíciót (i,j)=(0,0)(i,j)=(0,0)-t. Az F(TτX)0,0F(T_\tau X)_{0,0} a TτXT_\tau X bal felső 3×33\times 3 ablakának összege:

TτX sorai 0,1,2, oszlopai 0,1,2:000001067,összeg=0+0+0+0+0+1+0+6+7=14.T_\tau X\text{ sorai }0,1,2,\text{ oszlopai }0,1,2: \begin{matrix} 0&0&0\\ 0&0&1\\ 0&6&7 \end{matrix},\qquad \text{összeg}=0+0+0+0+0+1+0+6+7=14.

A jobb oldal a kimeneti rács nullával kitöltő eltolásából [TτF(X)]0,0=0[T_\tau F(X)]_{0,0}=0, mert (0,0)(0,0) a kimeneti nullasávban van (i=0<τh=1i=0<\tau_h=1). A 14≠014\neq0 eltérés pontosan a tétel alsó korlátját mutatja: az ablak a bemeneti nullasávba lóg, ezért nem az eredeti tartalom eltoltja. A belső tartomány itt 1≤i≤6−3=31\le i\le 6-3=3 és 1≤j≤31\le j\le3; a (3,3)(3,3) pozíció a felső korlátot is szemlélteti: F(TτX)3,3F(T_\tau X)_{3,3} ablaka a TτXT_\tau X 3–5. sora és oszlopa, vagyis az XX 2–4. sora és oszlopa, tehát F(TτX)3,3=F(X)2,2=[TτF(X)]3,3F(T_\tau X)_{3,3}=F(X)_{2,2}=[T_\tau F(X)]_{3,3}. A laborban a numerikus ellenőrzés ugyanezt a tartományt használja.

16.1.7 Labor: szélső padding, crop és stride eltérése

A labor egyetlen kis NumPy szkript, amely három eltolási implementáció — zero-fill, crop és circular —, valamint a stride hatását méri. A munkakönyvtár lab/n061. A kód float64-ben dolgozik, a tolerancia a belső tartományon 10−1210^{-12}, mert a műveletek véges floating-point összegek.

# workdir: lab/n061
import numpy as np

def corr_valid(x, k):
    """Valid cross-correlation, N=1, C=1. x:(H,W), k:(kh,kw)."""
    H, W = x.shape
    kh, kw = k.shape
    out = np.zeros((H - kh + 1, W - kw + 1), dtype=np.float64)
    for i in range(out.shape[0]):
        for j in range(out.shape[1]):
            out[i, j] = np.sum(x[i:i+kh, j:j+kw] * k)
    return out

def corr_valid_stride(x, k, s):
    H, W = x.shape
    kh, kw = k.shape
    ho = (H - kh) // s + 1
    wo = (W - kw) // s + 1
    out = np.zeros((ho, wo), dtype=np.float64)
    for i in range(ho):
        for j in range(wo):
            out[i, j] = np.sum(x[i*s:i*s+kh, j*s:j*s+kw] * k)
    return out

def shift_zero(x, tau):
    """Eltolás; a felszabaduló sáv nullával töltött."""
    th, tw = tau
    y = np.zeros_like(x)
    H, W = x.shape
    y[th:, tw:] = x[:H-th, :W-tw]
    return y

def shift_crop(x, tau):
    """Eltolás; a kilógó részt eldobjuk, a kép mérete csökken."""
    th, tw = tau
    return x[th:, tw:]

def shift_circular(x, tau):
    """Körkörös eltolás (np.roll)."""
    th, tw = tau
    return np.roll(x, (th, tw), axis=(0, 1))

np.random.seed(20261020)
x = np.random.rand(8, 8).astype(np.float64)
k = np.array([[1.0, 2.0, 1.0],
              [2.0, 4.0, 2.0],
              [1.0, 2.0, 1.0]], dtype=np.float64)  # Gauss-szerű 3x3 kernel

tau = (1, 1)

# 1) zero-fill shift
F_x = corr_valid(x, k)
T_x = shift_zero(x, tau)
F_Tx = corr_valid(T_x, k)
T_Fx = np.zeros_like(F_x)
T_Fx[tau[0]:, tau[1]:] = F_x[:F_x.shape[0]-tau[0], :F_x.shape[1]-tau[1]]
# belső tartomány a tétel szerint: tau_h <= i < F_Tx.shape[0], stb.
diff_zero = np.abs(F_Tx - T_Fx)
print("zero-fill, belső max |diff|:", diff_zero[tau[0]:, tau[1]:].max())
print("zero-fill, teljes max |diff|:", diff_zero.max())

# 2) crop shift
C_x = shift_crop(x, tau)  # 7x7
F_Cx = corr_valid(C_x, k)  # 5x5
# a közös tartomány a teljes F_Cx
T_Fx_crop = F_x[tau[0]:F_x.shape[0], tau[1]:F_x.shape[1]]  # 5x5, mert F_x 6x6
diff_crop = np.abs(F_Cx - T_Fx_crop)
print("crop, közös tartomány max |diff|:", diff_crop.max())

# 3) circular shift
C2_x = shift_circular(x, tau)
F_C2x = corr_valid(C2_x, k)
diff_circ = np.abs(F_C2x - T_Fx)
print("circular, belső max |diff|:", diff_circ[tau[0]:, tau[1]:].max())
print("circular, teljes max |diff|:", diff_circ.max())

# 4) stride 2
s = 2
F_sx = corr_valid_stride(x, k, s)          # 3x3
# páros eltolás: tau = (2,0) -> kimeneti (1,0) eltolás
T2_x = np.zeros_like(x)
T2_x[2:, :] = x[:6, :]
F_sT2x = corr_valid_stride(T2_x, k, s)      # 3x3
T1_Fsx = np.zeros_like(F_sx)
T1_Fsx[1:, :] = F_sx[:F_sx.shape[0]-1, :]
diff_stride_even = np.abs(F_sT2x - T1_Fsx)
print("stride 2, páros eltolás belső max |diff|:",
      diff_stride_even[1:, :].max())

# páratlan eltolás: tau=(1,0) — nincs megfelelő kimeneti egész eltolás
T1_x = np.zeros_like(x)
T1_x[1:, :] = x[:7, :]
F_sT1x = corr_valid_stride(T1_x, k, s)
# referencia: F_sx eltolás nélkül; eltérés nem lehet nulla
diff_stride_odd = np.abs(F_sT1x - F_sx)
print("stride 2, páratlan eltolás teljes max |diff|:", diff_stride_odd.max())

A várható, nem futtatott kimenet jellege. A zero-fill esetben a belső tartományon a maximális eltérés 00 (gépi pontossággal), a teljes tartományon viszont nem nulla, mert a határon a nulla-sáv hatása megjelenik. A crop shift esetén a közös tartományon az eltérés 00, de a kimenet mérete kisebb, így a határinformáció elveszik. A circular shift esetén a belső tartományon is eltérés lép fel, mert a körkörös eltolás a kép másik széléről hoz be elemeket az ablakba; a valid cross-correlation lineáris határfeltételt használ, ezért a két operátor nem cserélhető fel. A stride 2 esetén a páros eltolásra a belső tartományon az eltérés 00, a páratlan eltolásra a teljes tartományon sem nulla. A konkrét számok függenek a seedtől, ezért szándékosan nem adunk meg előre rögzített értékeket; a hallgató feladata a futtatás és a fenti viselkedés ellenőrzése. A közölt elvárások nem helyettesítik a laborban rögzített mérési jegyzőkönyvet.

16.1.8 Feladatok

16.1.8.1 F1 feladat (fogalmi, nehézség 1)

Adjon példát olyan FF operátorra, amely a (3) értelemben eltolási ekvivariáns, de nem invariáns, és olyanra, amely invariáns. Indokolja meg, hogy a globális átlagpooling miért invariáns a nulla-paddingelt eltolásra a belső tartományon, és mi történik a határon. Elvárt átadandó eredmény: a két példa az operátoregyenlettel ellenőrizve, legalább egy ellenpélda a határviselkedésre.

16.1.8.2 F2 feladat (levezetési/bizonyítási, nehézség 2)

Bizonyítsa be a stride-ss cross-correlation eltolási ekvivarianciáját a stride-részcsoporton: minden m∈ℤ2m\in\mathbb Z^2-re és a belső tartományon teljesüljön

Fs(TsmX)o,i′,j′=[TmFs(X)]o,i′,j′.F_s(T_{sm}X)_{o,i',j'}=[T_m F_s(X)]_{o,i',j'}.

Adja meg pontosan a belső tartományt H,W,kh,kw,s,mH,W,k_h,k_w,s,m függvényében. Elvárt átadandó eredmény: a tétel feltevésekkel, a bizonyítás a definícióból, és egy 8×88\times 8-as bemenetre s=2s=2, m=(1,0)m=(1,0) mellett a belső tartomány explicit indexhalmaza.

16.1.8.3 F3 feladat (implementációs, nehézség 2)

Egészítse ki a labor kódját egy check_equiv függvénnyel, amely adott FF, TτT_\tau, XX és KK esetén visszaadja (a) a teljes tartományon, (b) a belső tartományon a maximális abszolút eltérést. Futtassa a labor zero-fill esetére. Elvárt átadandó eredmény: a függvény kódja, a két számérték, és egy assert állítás, amely a belső tartományon 10−1210^{-12} alatti eltérést követel meg.

16.1.8.4 F4 feladat (hibakeresési, nehézség 2)

Egy hallgató a következőt állítja: „Mivel a np.roll\mathrm{np.roll} körkörösen tolja el a képet, a corr_valid(np.roll(x, tau), k) eredménye mindig megegyezik np.roll(corr_valid(x, k), tau) eredményével.” Lokalizálja az állítás hibáját, adjon konkrét 4×44\times 4-es bemenetet, 2×22\times 2-es kernelt és τ=(1,0)\tau=(1,0) eltolást, amelyre az egyenlőség megsérül, és magyarázza el a hiba okát a határfeltételek nyelvén. Elvárt átadandó eredmény: az ellenpélda konkrét számaival, a két kimenet kiszámítva, és a javítás (mely shift-definícióval lenne igaz az állítás).

16.1.8.5 F5 feladat (kísérleti/transzfer, nehézség 3)

Tervezzen kísérletet arra, hogy megmérje: a GlyphLab osztályozó CNN (a korábbi checkpoint) mennyire invariáns az eltolásra a gyakorlatban. Vegye figyelembe a szerződést: a tesztkép eltolásakor a nulla-paddingelt részek új tartalmat visznek be, ezért az eltolást csak a kép belsejéből vett cropként, vagy a valid tartomány eltolásaként definiálja. Adjon meg nullhipotézist, metrikát (például a helyes osztály logitjának átlagos változása vagy a pontosság), a teszteléshez használt eltolástartományt, és azt, hogy miért nem elegendő egyetlen eltolás. Elvárt átadandó eredmény: egy kísérleti terv a protokoll elemeivel (adat, split, baseline, változó, metrika, korlát), futtatott eredmény nélkül.

16.1.9 Megoldások és indoklás

16.1.9.1 F1 megoldása

Az identitás F(X)=XF(X)=X ekvivariáns, mert TτX=TτXT_\tau X = T_\tau X triviálisan, de nem invariáns, mert az eltolt kép általában különbözik az eredetitől. A globális átlagpooling

G(X)=1HW∑i=0H−1∑j=0W−1Xi,jG(X)=\frac{1}{HW}\sum_{i=0}^{H-1}\sum_{j=0}^{W-1}X_{i,j}

invarianciája a nulla-paddingelt eltolásra a belső tartományon abból következik, hogy az eltolás a pixelek összegét nem változtatja, csak a helyüket, amíg nulla-sáv nem lép be. Ha τ>0\tau>0, akkor a nulla-paddingelt képből τh⋅W+τw⋅H−τhτw\tau_h\cdot W+\tau_w\cdot H-\tau_h\tau_w nulla elem kerül a helyére, így az átlag csökken: G(TτX)=HW−τhW−τwH+τhτwHWG(X)G(T_\tau X)=\frac{HW-\tau_h W-\tau_w H+\tau_h\tau_w}{HW}G(X) a hányados erejéig. Tehát a határon az invariancia sérül. Ellenpélda: XX csupa 1-es 4×44\times 4-es kép, τ=(1,0)\tau=(1,0); ekkor G(X)=1G(X)=1, de G(TτX)=3⋅4/16=0.75G(T_\tau X)=3\cdot 4/16=0.75.

16.1.9.2 F2 megoldása

A stride-ss cross-correlation definíciója:

Fs(X)o,i′,j′=∑c∑p=0kh−1∑q=0kw−1Ko,c,p,qXc,i′s+p,j′s+q+bo.F_s(X)_{o,i',j'}=\sum_c\sum_{p=0}^{k_h-1}\sum_{q=0}^{k_w-1}K_{o,c,p,q}\,X_{c,\,i's+p,\,j's+q}+b_o.

Helyettesítsük be a TsmT_{sm} eltolást, ahol m=(mh,mw)m=(m_h,m_w):

Fs(TsmX)o,i′,j′=∑c∑p,qKo,c,p,qXc,i′s+p−smh,j′s+q−smw+bo.F_s(T_{sm}X)_{o,i',j'} =\sum_c\sum_{p,q}K_{o,c,p,q}\,X_{c,\,i's+p-sm_h,\,j's+q-sm_w}+b_o.

Az XX-index átrendezve: i′s−smh+p=(i′−mh)s+pi's-sm_h+p=(i'-m_h)s+p. Ez pontosan az Fs(X)F_s(X) definíciója az (i′−mh,j′−mw)(i'-m_h,j'-m_w) kimeneti pozícióra, feltéve, hogy az indexek a tartományban vannak. A belső tartomány: a TsmXT_{sm}X ablaknak teljesen az eltolt eredeti tartalomban kell lennie, azaz i′s+p≥smhi's+p\ge sm_h minden pp-re és i′s+p≤H−1i's+p\le H-1 is, hasonlóan jj-re. Innen

mhs≤i′s≤H−kh,mws≤j′s≤W−kw,m_h s\le i's\le H-k_h,\qquad m_w s\le j's\le W-k_w,

vagyis mh≤i′≤⌊(H−kh)/s⌋m_h\le i'\le \lfloor(H-k_h)/s\rfloor és mw≤j′≤⌊(W−kw)/s⌋m_w\le j'\le \lfloor(W-k_w)/s\rfloor. A 8×88\times 8-as bemenetre kh=kw=3k_h=k_w=3, s=2s=2, m=(1,0)m=(1,0) esetén a belső tartomány i′∈[1,2]i'\in[1,2], j′∈[0,2]j'\in[0,2] (mert ⌊(8−3)/2⌋=2\lfloor(8-3)/2\rfloor=2). Ez a kimeneti 3×33\times 3-as rács alsó 2 sora.

16.1.9.3 F3 megoldása

A függvény:

def check_equiv(F, shift, x, k, tau):
    """F: (x,k)->out cross-correlation. Visszaadja a teljes és belső max eltérést."""
    F_x = F(x, k)
    T_x = shift(x, tau)
    F_Tx = F(T_x, k)
    T_Fx = np.zeros_like(F_x)
    th, tw = tau
    T_Fx[th:, tw:] = F_x[:F_x.shape[0]-th, :F_x.shape[1]-tw]
    diff = np.abs(F_Tx - T_Fx)
    full = diff.max()
    interior = diff[th:, tw:].max()
    return full, interior

full, interior = check_equiv(corr_valid, shift_zero, x, k, (1, 1))
assert interior < 1e-12, f"belső eltérés {interior}"
print(f"teljes={full}, belső={interior}")

A belső eltérésre 00 várható, a teljesre a seedtől függő pozitív érték. Az ellenőrzés azért használ float64-et és 10−1210^{-12} küszöböt, mert a cross-correlation összegekben legfeljebb khkwk_hk_w tagú kerekítés halmozódik; a 10−1210^{-12} a gépi epszilon (2.2⋅10−162.2\cdot 10^{-16}) és a 99 tagú összeg szorzatának nagyságrendjébe esik.

16.1.9.4 F4 megoldása

Legyen X=[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]X=[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]], kernel [[1,0],[0,0]][[1,0],[0,0]], τ=(1,0)\tau=(1,0). A corr_valid kimenete 3×33\times 3:

F(X)=(12356791011).F(X)=\begin{pmatrix}1&2&3\\ 5&6&7\\ 9&10&11\end{pmatrix}.

A np.roll(X,(1,0))\mathrm{np.roll}(X,(1,0)) sorai: [13,14,15,16][13,14,15,16], majd az eredeti első három sor. A corr_valid ezen:

F(roll(X))=(131415123567).F(\mathrm{roll}(X))=\begin{pmatrix}13&14&15\\ 1&2&3\\ 5&6&7\end{pmatrix}.

A np.roll(F(X),(1,0))\mathrm{np.roll}(F(X),(1,0)) pedig:

(91011123567).\begin{pmatrix}9&10&11\\ 1&2&3\\ 5&6&7\end{pmatrix}.

A két mátrix első sora eltér (13,14,1513,14,15 vs. 9,10,119,10,11), tehát az állítás hamis. A hiba oka: a körkörös eltolás a kép alsó sorát a felsőre hozza, ezért a kernel olyan elemeket lát, amelyek az eredeti kép másik széléről származnak. A valid cross-correlation lineáris határfeltételt használ, ezért a két operátor nem cserélhető fel. Az állítás akkor lenne igaz, ha a cross-correlation is körkörös paddinget használna; a labor corr_valid függvénye ezt nem teszi.

16.1.9.5 F5 megoldása (minta)

Kérdés: A tanított GlyphLab-osztályozó predikciója mennyire stabil a bemeneti kép kis, nulla-padding nélküli eltolásaira?

Adat és split: a GlyphLab test split 60 képe; a kísérlet során a test képeket nem használjuk modellválasztásra, csak a végén értékeljük. A checkpoint a val spliten legjobb modell.

Eltolás-definíció: hogy elkerüljük a nulla-padding hatását, a 24×2424\times 24-es képet először középen 20×2020\times 20-ra vágjuk, majd ezt a 4×44\times 4-es rácson toljuk el a 24×2424\times 24-es ablakon belül: τ∈{0,1,2,3,4}2\tau\in\{0,1,2,3,4\}^2, összesen 25 változat képenként. Így az eltolás csak valódi képtartalmat mozgat, nulla-sáv nem lép fel.

Nullhipotézis: a helyes osztály logitja az eltolás hatására nem változik szignifikánsan többet, mint a kép újra-mintavételezésének numerikus zaja.

Metrika: (a) a helyes osztály logitjának max-csökkenése a 25 eltolás között, képenként átlagolva; (b) a pontosság változása az eltolt képeken. Baseline: a checkpoint pontossága az eltolás nélküli testen.

Korlát: a GlyphLab nem természetes képi benchmark, ezért az eredmény nem általánosítható valós alkalmazásokra; a minta 60 kép, a bootstrap egység a scene_id.

16.1.10 Tipikus tévedés: „a CNN automatikusan invariáns minden eltolásra”

A leggyakoribb tévedés azt állítja, hogy egy konvolúciós réteg, mivel „súlymegosztást” használ, a kimenetét változatlanul hagyja az eltolással szemben. Ez hamis: a cross-correlation ekvivariáns, tehát a kimenet ugyanúgy eltolódik, nem marad a helyén. Invarianciát csak a térbeli dimenziókat összevonó műveletek (globális pooling, vagy a stride-dal kombinált pooling rétegek) hozhatnak létre, és azok is csak korlátozott mértékben.

Konkrét ellenpélda: X=[1,0,0]X=[1,0,0] 1D jel, K=[1,0]K=[1,0] kernel, valid cross-correlation stride 1, padding 0. Ekkor F(X)=[1,0]F(X)=[1,0]. A τ=1\tau=1 eltolásra TτX=[0,1,0]T_\tau X=[0,1,0], és F(TτX)=[0,1]F(T_\tau X)=[0,1]. Ez pontosan TτF(X)T_\tau F(X), vagyis a kimenet eltolódott, nem maradt [1,0][1,0]. Az invariáns viselkedéshez a kimenetnek [1,0][1,0]-nak kellene maradnia, ami nem teljesül.

A [P03] absztraktja szerint a modern CNN-architektúrák downsampling-rétegei miatt a hálózatok a gyakorlatban sem teljesen shift-invariánsak; a cikk teljes módszerszakasza azonban még olvasásra vár, ezért ebből itt csak az absztrakt szintű állítást idézzük.

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

Ellenőrizze a megértést az alábbi kérdésekkel, mielőtt továbblép:

  1. Mi a különbség a (3) és a (4) egyenlet között? Melyik oldalon hat még TτT_\tau a kimenetre?
  2. A tételben miért szerepel az i≥τhi\ge\tau_h, j≥τwj\ge\tau_w alsó korlát? Rajzolja fel a 6×66\times 6-os példa nulla-sávját és a belső tartományt.
  3. Miért éppen ℤ2\mathbb Z^2 egy részcsoportja a stride-ss eltolások halmaza, és miért nem az egész ℤ2\mathbb Z^2?
  4. A körkörös shift és a valid cross-correlation miért nem cserélhető fel? Kapcsolja össze a 13.4. Határkezelés és frekvenciaintuíció egységben tanult lineáris és körkörös határfeltétellel.
  5. Hogyan függ össze az equivariance a kernel 15.1. Súly- és biasgradiens alfejezetben tárgyalt súlymegosztásával? Mi történne, ha a kernel minden pozícióban különböző súlyt használna?

Rövid visszahívás: a 4.1. Függvény, határérték és derivált egységben a függvényeket leképezésként definiáltuk; a (3) egyenlet két leképezés, F∘TτF\circ T_\tau és Tτ∘FT_\tau\circ F egyenlősége egy adott tartományon. Ez ugyanaz a szerkezet, mint a lineáris operátorok kommutálása, csak itt a tartomány korlátozott. A 15.1. Súly- és biasgradiens egységben levezetett kernelgradiens-összegzés éppen a súlymegosztás következménye; ugyanez a megosztás teszi lehetővé, hogy az eltolás csak az indexeket mozgassa.

16.1.12 Rövid összefoglaló

Az eltolási ekvivariancia és invariancia két külön operátoregyenlet. Az ekvivariancia, F(TτX)=TτF(X)F(T_\tau X)=T_\tau F(X), azt jelenti, hogy a kimenet az eltolással együtt mozog; az invariancia, F(TτX)=F(X)F(T_\tau X)=F(X), azt, hogy a kimenet nem változik. A valid cross-correlation stride 1, padding 0 mellett a belső tartományon ekvivariáns; a határon a nulla-padding miatt az állítás sérül. A stride ss esetén az ekvivariancia csak az sℤ2s\mathbb Z^2 részcsoport eltolásaira áll fenn. A labor a zero-fill, crop és circular shift, valamint a stride hatását méri. Egy CNN tehát nem automatikusan invariáns: az invarianciát külön aggregáló rétegeknek kell létrehozniuk.

16.1.13 Következő alkalmazás

A következő, 16.2. Pooling, downsampling és aliasing egység a pooling rétegeket vizsgálja. Ott az itt definiált invarianciafogalom válik mérhetővé: a max- és átlagpooling stride-dal kombinálva lokális invarianciát ad, de a downsampling aliasing-hoz vezethet. A 16.3. Elméleti és effektív recepciós mező egység pedig a recepciós mezőt általánosítja a többrétegű hálózatokra, ahol az ekvivariancia rétegenkénti összetétele kerül elő.

16.1.14 Felhasznált források