14.1 Stride, padding, dilation és outputméret

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

Ebben az egységben egyetlen célt járunk körbe pontosan: adott bemeneti képméret, kernel, padding, stride és dilation mellett mekkora lesz a CNN-réteg kimeneti térbeli mérete, és miért éppen ez a méret. A 13.4. Határkezelés és frekvenciaintuíció egységben már láttuk, hogy a határfeltétel, például a zero padding, a cross-correlation definíciójának része; most ezt a gondolatot általánosítjuk a CNN-réteg összes geometriai paraméterére. A 13.1. Kép mint diszkrét többcsatornás jel egységből visszahozzuk a mintavételi rácsot, a 2.1. Python, NumPy és tenzoralak egységből pedig a tenzoralakok és a broadcasting ellenőrzésének szokását.

Induló becslésként gondoljunk egy 7×77\times7-es képre és egy 3×33\times3-as kernelre, stride 11 mellett, padding nélkül. Hány pozícióba tudjuk a kernelt teljes egészében rátenni? A mag bal felső sarka a 0,1,2,3,40,1,2,3,4 oszlopokban lehet, ezért a kimenet 5×55\times5-nek ígérkezik. Kérdés: hogyan változik ez, ha lépésközt, kitöltést vagy tágítást kapcsolunk be, és mi a közös, bizonyítható szabály?

14.1.2 Definíciók: geometriai paraméterek és tenzoralakok

A bemenet egy X∈ℝN×Cin×H×WX\in\mathbb R^{N\times C_{in}\times H\times W} NCHW tensor, ahol HH a magasság, WW a szélesség. A groups g=1g=1 esetére szorítkozunk, tehát a konvolúciós mag

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

A térbeli paraméterek:

Jel Tartomány Jelentés
kh,kwk_h,k_w pozitív egész kernel magassága és szélessége
ph,pwp_h,p_w nemnegatív egész szimmetrikus zero padding a két dimenzióban
sh,sws_h,s_w pozitív egész stride, azaz lépésköz
dh,dwd_h,d_w pozitív egész dilation, azaz tágítási távolság

A dilation azt mondja meg, hogy a kernel két szomszédos együtthatója hány bemeneti rácspontra kerül egymástól. A kernel ténylegesen lefedett, effektív kiterjedése (kernel extent) ezért nem kk, hanem

ℓh=dh(kh−1)+1,ℓw=dw(kw−1)+1.\ell_h=d_h(k_h-1)+1,\qquad \ell_w=d_w(k_w-1)+1.

Például kh=3,dh=2k_h=3,d_h=2 esetén a három kernelpozíció a 0,2,40,2,4 bemeneti indexeket fedi le, tehát a kiterjedés 55, nem 33.

A kimenet térbeli alakja Hout×WoutH_{out}\times W_{out}. A [D10] dokumentációban használt programozói konvenció szerint a Conv2d keresztkorrelációt számol, azaz a kernel súlyait nem forgatja meg. Egy jj kimeneti indexhez a kernel első (r=0)(r=0) együtthatójának horgonypozíciója a magasság mentén

jsh−ph,j s_h-p_h,

az rr-edik kernelpozíció pedig a

jsh−ph+dhrj s_h-p_h+d_h r

bemeneti indexet mintavételezi. A zero padding miatt az eredeti [0,H−1][0,H-1] tartományon kívüli, de a [−ph,H−1+ph][-p_h,H-1+p_h] kiterjesztett tartományon belüli indexeket nulla helyettesíti; az ezen kívül eső horgonypozíciókhoz már nincs érvényes kimeneti ablak.

14.1.3 A kimeneti méret levezetése

A következő állítást az index-tartományból teljes egészében levezetjük; ez saját levezetés, amely a [D10] dokumentált indexezését használja.

Tétel (szimmetrikus paddinggel). Legyen H,kh,dh,shH,k_h,d_h,s_h pozitív egész és php_h nemnegatív egész. Egy térbeli dimenzió mentén a keresztkorreláció érvényes kimeneti indexeinek halmaza

𝒪h={j∈ℤ≥0:∀r∈{0,…,kh−1},−ph≤jsh−ph+dhr≤H−1+ph}.\mathcal O_h=\left\{j\in\mathbb Z_{\ge0}:\ \forall r\in\{0,\ldots,k_h-1\},\quad -p_h\le j s_h-p_h+d_h r\le H-1+p_h\right\}.

Ha 𝒪h\mathcal O_h nem üres, akkor 𝒪h={0,1,…,Hout−1}\mathcal O_h=\{0,1,\ldots,H_{out}-1\}, ahol

Hout=⌊H+2ph−dh(kh−1)−1sh⌋+1.H_{out}=\left\lfloor\frac{H+2p_h-d_h(k_h-1)-1}{s_h}\right\rfloor+1.

A 𝒪h\mathcal O_h pontosan akkor üres, ha H+2ph<dh(kh−1)+1H+2p_h<d_h(k_h-1)+1; ezt a beállítást érvénytelen kimenetnek nevezzük, és a könyvtári forward ilyenkor alakhibát ad.

Bizonyítás. Mivel j≥0j\ge0, sh>0s_h>0, dh>0d_h>0 és r≥0r\ge0, a bal oldali egyenlőtlenség

−ph≤jsh−ph+dhr-p_h\le j s_h-p_h+d_h r

mindig teljesül. A jobb oldali feltétel minden rr indexre akkor és csak akkor áll fenn, ha a legnagyobb r=kh−1r=k_h-1 mellett sem sérül:

jsh−ph+dh(kh−1)≤H−1+ph.j s_h-p_h+d_h(k_h-1)\le H-1+p_h.

Átrendezve:

jsh≤H+2ph−dh(kh−1)−1.j s_h\le H+2p_h-d_h(k_h-1)-1.

A legnagyobb megengedett egész jj ezért

Jmax=⌊H+2ph−dh(kh−1)−1sh⌋.J_{\max}=\left\lfloor\frac{H+2p_h-d_h(k_h-1)-1}{s_h}\right\rfloor.

A feltétel bal oldala jj-ben monoton növekvő, ezért ha Jmax≥0J_{\max}\ge0, akkor minden j=0,1,…,Jmaxj=0,1,\ldots,J_{\max} index teljesíti az összes egyenlőtlenséget, tehát az érvényes indexek halmaza egy kezdőszelet. Így

Hout=|{0,…,Jmax}|=Jmax+1=⌊H+2ph−dh(kh−1)−1sh⌋+1.H_{out}=|\{0,\ldots,J_{\max}\}|=J_{\max}+1 =\left\lfloor\frac{H+2p_h-d_h(k_h-1)-1}{s_h}\right\rfloor+1.

Végül 𝒪h\mathcal O_h akkor üres, ha Jmax<0J_{\max}<0, azaz a számláló kisebb, mint 00. Ez éppen a

H+2ph<dh(kh−1)+1H+2p_h<d_h(k_h-1)+1

feltétellel ekvivalens. ▫\square

A szélességre a teljesen azonos levezetés adódik, H,ph,sh,dh,khH,p_h,s_h,d_h,k_h helyett W,pw,sw,dw,kwW,p_w,s_w,d_w,k_w szereplőkkel:

Wout=⌊W+2pw−dw(kw−1)−1sw⌋+1.W_{out}=\left\lfloor\frac{W+2p_w-d_w(k_w-1)-1}{s_w}\right\rfloor+1.

A magasságra és szélességre vonatkozó feltételek egymástól függetlenek. A réteg akkor ad érvényes kimenetet, ha Hout≥1H_{out}\ge1 és Wout≥1W_{out}\ge1 egyszerre teljesül.

Két fontos megjegyzés tartozik a tétel hatásköréhez. Először: a formula 2p2p-t tartalmaz, mert a paddinget a térbeli dimenzió mindkét oldalán azonos méretűnek tételeztük fel. Ha egy API vagy egy F.pad hívás aszimmetrikus paddinget használ, phleftp_h^{\mathrm{left}} bal és phrightp_h^{\mathrm{right}} jobb kitöltéssel, akkor a tétel bizonyításában 2ph2p_h helyére phleft+phrightp_h^{\mathrm{left}}+p_h^{\mathrm{right}} kerül, mert a jobb széli feltétel csak a teljes padding mennyiségét érzékeli. Másodszor: a padding='valid' szöveges opció nem azonos a „van legalább egy kimeneti ablak” matematikai értelemben vett érvényességgel; a 'valid' egyszerűen a p=0p=0 választás rövid neve.

14.1.4 Kézi kis példa

Legyen a bemenet X∈ℝ1×2×6×5X\in\mathbb R^{1\times2\times6\times5}, tehát N=1,Cin=2,H=6,W=5N=1,C_{in}=2,H=6,W=5. Válasszunk kh=kw=3k_h=k_w=3, ph=1,pw=0p_h=1,p_w=0, sh=sw=2s_h=s_w=2 és dh=dw=1d_h=d_w=1 paramétereket. A mag effektív kiterjedése mindkét dimenzióban 3⋅1−1+1=33\cdot1-1+1=3.

Magasságra:

Hout=⌊6+2⋅1−1⋅(3−1)−12⌋+1=⌊6+2−2−12⌋+1=⌊52⌋+1=3.H_{out}=\left\lfloor\frac{6+2\cdot1-1\cdot(3-1)-1}{2}\right\rfloor+1 =\left\lfloor\frac{6+2-2-1}{2}\right\rfloor+1 =\left\lfloor\frac{5}{2}\right\rfloor+1=3.

Szélességre:

Wout=⌊5+0−1⋅(3−1)−12⌋+1=⌊22⌋+1=2.W_{out}=\left\lfloor\frac{5+0-1\cdot(3-1)-1}{2}\right\rfloor+1 =\left\lfloor\frac{2}{2}\right\rfloor+1=2.

A kimenet térbeli alakja tehát 3×23\times2. Ellenőrizzük a magassági indexeket: j=0j=0-nál a horgonypozíció 0⋅2−1=−10\cdot2-1=-1, a lefedett indexek {−1,0,1}\{-1,0,1\}, a −1-1 a bal oldali paddingból érkezik. j=2j=2-nél a lefedett indexek {3,4,5}\{3,4,5\}, ez még érvényes, mert H−1+ph=6H-1+p_h=6 a jobb széli paddinget is tartalmazza. j=3j=3-nál a lefedés {5,6,7}\{5,6,7\} lenne, de 77 már túlmegy a kiterjesztett tartományon, ezért j=3j=3 nem érvényes. A számított 33 kimeneti index tehát pontosan fedi a lehetséges pozíciókat.

Egy gyors, önállóan futtatható kontroll ugyanerre:

import torch

H, W, k, p, s, d = 6, 5, 3, 1, 2, 1
formula = ((H + 2*p - d*(k-1) - 1)//s + 1,
           (W + 2*p - d*(k-1) - 1)//s + 1)
conv = torch.nn.Conv2d(2, 4, k, stride=s, padding=p, dilation=d,
                       bias=False, dtype=torch.float32, device="cpu")
y = conv(torch.zeros(1, 2, H, W, dtype=torch.float32, device="cpu"))
print("formula:", formula, "torch:", tuple(y.shape[2:]))

A képletből számított, nem futtatott várt kimenet: formula: (3, 2) torch: (3, 2). A Cin=2,Cout=4C_{in}=2,C_{out}=4 választás azt is ellenőrzi, hogy a csatornák száma nem befolyásolja a térbeli alakot.

14.1.5 Labor: alakteszt legalább hat beállításra

A labor célja, hogy ne egyetlen példán higgyünk a formulának, hanem egymástól eltérő beállításokon, nemnégyzetes bemenet és kernel mellett is összevessük a saját számítást a Conv2d tényleges kimeneti alakjával. A teszt determinisztikus, ezért az alakegyezéshez semmilyen lebegőpontos tolerancia nem kell; a seed csak a szokásos reprodukálhatósági kontrollt rögzíti.

Munkakönyvtár: n053_lab/. Futtatás: python shape_test.py.

# n053_lab/shape_test.py
import torch


def out1d(length, kernel, pad, stride, dilation):
    """Egy térbeli dimenzió kimeneti mérete szimmetrikus paddinggel."""
    assert length >= 1 and kernel >= 1 and stride >= 1 and dilation >= 1
    assert pad >= 0
    return (length + 2 * pad - dilation * (kernel - 1) - 1) // stride + 1


def expected_shape(H, W, kh, kw, ph, pw, sh, sw, dh, dw):
    return (out1d(H, kh, ph, sh, dh), out1d(W, kw, pw, sw, dw))


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

    # (H, W, kh, kw, ph, pw, sh, sw, dh, dw, név)
    cases = [
        (5, 5, 3, 3, 0, 0, 1, 1, 1, 1, "valid, négyzetes"),
        (7, 5, 3, 3, 1, 1, 1, 1, 1, 1, "nemnégyzetes, padding"),
        (8, 10, 3, 5, 0, 0, 1, 1, 1, 1, "nemnégyzetes input és kernel"),
        (7, 6, 3, 3, 0, 0, 2, 2, 1, 1, "stride 2, padding nélkül"),
        (9, 8, 3, 3, 0, 0, 1, 1, 2, 2, "dilation 2"),
        (5, 4, 4, 4, 1, 1, 2, 2, 1, 1, "padding+stride"),
        (13, 7, 5, 5, 0, 0, 2, 2, 1, 1, "nagyobb nemnégyzetes"),
        (6, 6, 6, 6, 0, 0, 1, 1, 1, 1, "éppen 1x1 kimenet"),
    ]

    for (H, W, kh, kw, ph, pw, sh, sw, dh, dw, name) in cases:
        exp = expected_shape(H, W, kh, kw, ph, pw, sh, sw, dh, dw)
        x = torch.zeros(1, 2, H, W, dtype=dtype, device=device)
        conv = torch.nn.Conv2d(2, 3, (kh, kw),
                               stride=(sh, sw),
                               padding=(ph, pw),
                               dilation=(dh, dw),
                               bias=False,
                               dtype=dtype, device=device)
        got = tuple(conv(x).shape[2:])
        assert got == exp, (name, got, exp)
        print(f"{name:30s} formula={exp} torch={got}")

    # Érvénytelen beállítás: a formulának <= 0 méretet kell adnia.
    # A Conv2d forward ilyenkor RuntimeError-t ad, ezért itt csak a formulát teszteljük.
    invalid = [(3, 4, 0, 1, 1), (4, 5, 0, 1, 1)]
    for L, k, p, s, d in invalid:
        value = out1d(L, k, p, s, d)
        assert value <= 0, (L, k, p, s, d, value)
        print(f"érvénytelen L={L},k={k},p={p},s={s},d={d}: formula={value}")
    print("Minden alaktartalom-ellenőrzés rendben.")


if __name__ == "__main__":
    main()

A fenti kódot az írás pillanatában nem futtattuk; az alábbi sorok a képletből közvetlenül számított, jelölt várt kimenet, nem mért futás:

valid, négyzetes                 formula=(3, 3) torch=(3, 3)
nemnégyzetes, padding            formula=(7, 5) torch=(7, 5)
nemnégyzetes input és kernel     formula=(6, 6) torch=(6, 6)
stride 2, padding nélkül         formula=(3, 2) torch=(3, 2)
dilation 2                       formula=(5, 4) torch=(5, 4)
padding+stride                   formula=(2, 2) torch=(2, 2)
nagyobb nemnégyzetes             formula=(5, 2) torch=(5, 2)
éppen 1x1 kimenet                formula=(1, 1) torch=(1, 1)
érvénytelen L=3,k=4,p=0,s=1,d=1: formula=0
érvénytelen L=4,k=5,p=0,s=1,d=1: formula=0

A teszt fontos tanulsága, hogy a validitási feltétel külön vizsgálandó: a Hout,WoutH_{out},W_{out} értékek nem negatív előjellel, hanem nullánál kisebb vagy azzal egyenlő értékkel jelzik, hogy a réteg geometriailag nem kivitelezhető.

14.1.6 Gyakori tévedés: a same padding nem mindig szimmetrikus

Gyakori félreértés, hogy a same padding pontosan ugyanaz, mint egyetlen szimmetrikus pp megadása. A fenti tétel csak szimmetrikus paddingre érvényes, ezért érdemes ellenpéldát számolni.

Legyen H=5H=5, kh=4k_h=4, sh=2s_h=2, dh=1d_h=1. Ha egy same típusú szabály a 3=⌈5/2⌉3=\lceil5/2\rceil kimeneti méretet célozza, akkor a kívánt teljes padding

(3−1)⋅2+4−5=3.(3-1)\cdot2+4-5=3.

Három padding pixel kellene összesen, ami két egész oldalkitöltéssel csak aszimmetrikusan, például bal 11, jobb 22 elosztásban valósítható meg. A szimmetrikus p=1p=1 ehhez kevés:

Hout=⌊5+2−3−12⌋+1=2,H_{out}=\left\lfloor\frac{5+2-3-1}{2}\right\rfloor+1=2,

a szimmetrikus p=2p=2 pedig ugyan 33 kimenetet ad, de 44 padding pixelt használ, tehát nem ugyanaz az operátor, mint a minimális 33 pixeles same változat:

Hout=⌊5+4−3−12⌋+1=3.H_{out}=\left\lfloor\frac{5+4-3-1}{2}\right\rfloor+1=3.

A tanulság nem az, hogy a same opció „rossz”, hanem hogy a mögöttes padding-elosztás, a támogatott stride-ok és az egész kimeneti méretre kerekítés szabálya könyvtáronként és verzióként eltérhet. A hordozható kódban érdemes explicit numerikus paddinget számolni, és a jelen formulát használni; a padding='same' viselkedését pedig külön, a saját környezetben ellenőrizni.

14.1.7 Önellenőrzés és korábbi fogalom visszahívása

Ellenőrizd a réteget a következő sorrendben: először az effektív kiterjedést, másodszor a validitási feltételt, harmadszor a floor formulát, végül mindkét térbeli dimenziót külön-külön. A 13.4. Határkezelés és frekvenciaintuíció tanulsága szerint a padding a lineáris operátor definíciójának része, ezért két eltérő padding-beállítás azonos kimeneti méret mellett is különböző számítást jelenthet. A 13.1. Kép mint diszkrét többcsatornás jel rácsindexelése nélkül a horgonypozíció feltételei nem írhatók fel. A későbbi 10.2. Affín réteg és aktiváció backward jellegű backward-levezetésekben a kimeneti indexhalmaz itteni lezártsága fogja garantálni, hogy a gradiensek hozzájárulásai egy jól meghatározott, véges ablakhalmazon összegződnek.

14.1.8 Feladatok

F1 fogalmi, nehézség 1. Definiáld az effektív kernel-kiterjedést. Adj két különböző (k,d)(k,d) párt, amelyeknek azonos az effektív kiterjedése, és mutasd meg egy L=11,h=0,s=1L=11,h=0,s=1 példán, hogy a kimeneti méretük azonos. Magyarázd el, miért nem jelenti ez, hogy a két operátor azonos. Átadandó: definíció, két paraméterpár, kimeneti méret és egy indoklás.

F2 levezetési, nehézség 2. Számítsd ki a kimeneti méretet H=10,W=7H=10,W=7, kh=4,kw=3k_h=4,k_w=3, ph=2,pw=1p_h=2,p_w=1, sh=3,sw=2s_h=3,s_w=2, dh=2,dw=1d_h=2,d_w=1 esetén. Ellenőrizd az indexfeltételből, hogy a magasság mentén j=2j=2 érvényes, de j=3j=3 nem; a szélesség mentén j=3j=3 érvényes, de j=4j=4 nem. Átadandó: mindkét dimenzió levezetése, a kiszámított Hout,WoutH_{out},W_{out} pár és a négy index feltételvizsgálata.

F3 implementációs, nehézség 2. Írj out1d és expected_shape függvényeket a tétel alapján, és teszteld legalább hat különböző beállításon, köztük nemnégyzetes inputtal. A valid eseteket hasonlítsd össze torch.nn.Conv2d kimeneti alakjával; egy érvénytelen beállításnál ellenőrizd, hogy a formula nullánál nem nagyobb értéket ad. Átadandó: teljes futtatható kód és az output másolata.

F4 hibakeresési, nehézség 2. Az alábbi függvény hibás:

def out_bad(L, k, p, s, d):
    return (L + 2*p - (k - 1) - 1)//s + 1

Lokalizáld a hibát, mutass ellenpéldát L=9,k=3,p=0,s=1,d=2L=9,k=3,p=0,s=1,d=2 bemenettel, írd le a hiba következményét egy többrétegű hálóra, majd add meg a javított függvényt és a visszaellenőrzést. Átadandó: hiba oka, a hibás és helyes kimenet, javított kód.

F5 kísérleti/transzfer, nehézség 3. Tervezz rövid, helyi protokollt annak eldöntésére, hogy a telepített PyTorch-verzió padding='same' üzemmódja hogyan viselkedik a H=5,k=4,s=2,d=1H=5,k=4,s=2,d=1 beállításra. Az összehasonlítás alapja legyen a szükséges teljes padding paritása: ha páratlan, akkor minimális same padding nem lehet szimmetrikus. Rögzítsd a verziót, a stride-ot, a mért vagy hiányzó kimeneti méretet és a következtetést a hordozhatóságról. Átadandó: protokoll, eredménytáblázat és értékelési kritérium.

14.1.9 Megoldások és indoklás

F1 megoldás. Az effektív kiterjedés ℓ=d(k−1)+1\ell=d(k-1)+1. A (k=5,d=1)(k=5,d=1) pár kiterjedése 1⋅4+1=51\cdot4+1=5; a (k=3,d=2)(k=3,d=2) pár kiterjedése 2⋅2+1=52\cdot2+1=5. L=11,p=0,s=1L=11,p=0,s=1 mellett mindkettőre

Lout=⌊11−1⋅(5−1)−11⌋+1=7.L_{out}=\left\lfloor\frac{11-1\cdot(5-1)-1}{1}\right\rfloor+1 =7.

A kimeneti méret azonos, de a d=2d=2 kernel a bemeneti indexeket 0,2,40,2,4 pozíciókban mintavételezi, a d=1d=1 kernel pedig 0,1,2,3,40,1,2,3,4 pozíciókban, ezért a súlyok más lineáris kombinációt képeznek.

F2 megoldás. Magasság: ℓh=2⋅(4−1)+1=7\ell_h=2\cdot(4-1)+1=7, a validitás H+2ph=14≥7H+2p_h=14\ge7 teljesül.

Hout=⌊10+4−2⋅3−13⌋+1=⌊73⌋+1=3.H_{out}=\left\lfloor\frac{10+4-2\cdot3-1}{3}\right\rfloor+1 =\left\lfloor\frac{7}{3}\right\rfloor+1=3.

A j=2j=2 index lefedése 2⋅3−2+{0,2,4,6}={4,6,8,10}2\cdot3-2+\{0,2,4,6\}=\{4,6,8,10\}, a maximum 10≤H−1+ph=1110\le H-1+p_h=11; j=3j=3-ra a maximum 13>1113>11. Szélesség: ℓw=1⋅(3−1)+1=3\ell_w=1\cdot(3-1)+1=3, W+2pw=9≥3W+2p_w=9\ge3,

Wout=⌊7+2−1⋅2−12⌋+1=⌊62⌋+1=4.W_{out}=\left\lfloor\frac{7+2-1\cdot2-1}{2}\right\rfloor+1 =\left\lfloor\frac{6}{2}\right\rfloor+1=4.

j=3j=3-nál a lefedés maximuma 3⋅2−1+2=7≤W−1+pw=73\cdot2-1+2=7\le W-1+p_w=7, tehát érvényes; j=4j=4-nél 9>79>7. A kimenet Hout=3,Wout=4H_{out}=3,W_{out}=4.

F3 megoldás. A labor shape_test.py kódja teljes megoldás. Egy tömör, önállóan futtatható ellenőrzés:

import torch

def out1d(L, k, p, s, d):
    return (L + 2*p - d*(k - 1) - 1)//s + 1

cases = [
    ((5, 5), 3, 0, 1, 1),
    ((7, 5), 3, 1, 1, 1),
    ((7, 6), 3, 0, 2, 1),
    ((9, 8), 3, 0, 1, 2),
    ((5, 4), 4, 1, 2, 1),
    ((13, 7), 5, 0, 2, 1),
]
for (H, W), k, p, s, d in cases:
    exp = (out1d(H, k, p, s, d), out1d(W, k, p, s, d))
    x = torch.zeros(1, 1, H, W)
    y = torch.nn.functional.conv2d(x, torch.zeros(1, 1, k, k),
                                  stride=s, padding=p, dilation=d)
    assert tuple(y.shape[2:]) == exp, (exp, y.shape)
    print((H, W), "->", exp)

assert out1d(3, 4, 0, 1, 1) <= 0
print("érvénytelen eset ellenőrizve")

Az alakegyezés egzakt egész összehasonlítás, ezért nincs szükség toleranciára. A nem futtatott, számított várt output: (5, 5) -> (3, 3), (7, 5) -> (7, 5), (7, 6) -> (3, 2), (9, 8) -> (5, 4), (5, 4) -> (2, 2), (13, 7) -> (5, 2).

F4 megoldás. A hiba a dilation hiánya: a függvény (k−1)(k-1)-et használ a tényleges d(k−1)d(k-1) kiterjedés helyett. A megadott példán a k=3,d=2k=3,d=2 kernel effektív kiterjedése 55, ezért a helyes eredmény

Lout=⌊9−2⋅2−11⌋+1=5,L_{out}=\left\lfloor\frac{9-2\cdot2-1}{1}\right\rfloor+1=5,

a hibás függvény viszont

9−2−11+1=7\frac{9-2-1}{1}+1=7

értéket ad. A következmény az, hogy a következő réteg vagy egy későbbi view/Linear alakillesztése rossz 77 mérettel számol, és a forward során alakhiba keletkezik, pedig a számítás geometriailag csak 55 kimeneti pozíciót enged meg. Javítás:

def out_fixed(L, k, p, s, d):
    return (L + 2*p - d*(k - 1) - 1)//s + 1

assert out_fixed(9, 3, 0, 1, 2) == 5
assert out_bad(9, 3, 0, 1, 2) == 7

F5 megoldásminta. A protokoll három esetet vizsgál, mert a szükséges teljes padding paritása mondja meg, hogy a minimális same padding lehet-e szimmetrikus. A kívánt kimeneti méretet Ĥ=⌈H/sh⌉\widehat{H}=\lceil H/s_h\rceil-ként rögzítjük, a szükséges teljes padding

Ptotal=max(0,(Ĥ−1)sh+dh(kh−1)+1−H).P_{\mathrm{total}}=\max(0,(\widehat{H}-1)s_h+d_h(k_h-1)+1-H).

Az H=5,k=4,s=2,d=1H=5,k=4,s=2,d=1 esetben Ĥ=3\widehat{H}=3 és

Ptotal=(3−1)⋅2+3+1−5=3.P_{\mathrm{total}}=(3-1)\cdot2+3+1-5=3.

A 33 páratlan, tehát a minimális same padding csak aszimmetrikusan valósítható meg; ha a telepített API ilyenkor hibát ad, vagy egész szimmetrikus paddingre kényszeríti a hívást, akkor a viselkedés nem írható le a jelen fejezet egyetlen pp paraméterével. A jegyzőkönyvben rögzíteni kell a torch.__version__ értéket, a padding='same' hívás kimeneti alakját vagy a RuntimeError szövegét, és azt, hogy a kapott alak megegyezik-e a szimmetrikus p=1p=1 vagy p=2p=2 változat valamelyikével. A következtetés csak a saját verzióra és erre a három paraméterkombinációra érvényes; ez nem általános API-teszt.

14.1.10 Rövid összefoglaló

A CNN-réteg térbeli kimeneti méretét a stride, a szimmetrikus padding, a kernelméret és a dilation együtt határozza meg. A kernel effektív kiterjedése d(k−1)+1d(k-1)+1; egy kimeneti index akkor érvényes, ha a horgonypozícióból indított összes mintavételi pont a paddinggel kiterjesztett tartományba esik. Az indexfeltételből levezettük a Hout=⌊(H+2p−d(k−1)−1)/s⌋+1H_{out}=\lfloor(H+2p-d(k-1)-1)/s\rfloor+1 formulát, és megadtuk a legalább egy kimeneti ablakot garantáló feltételt. A labor nyolc beállításon, nemnégyzetes inputtal és kernelmel ellenőrzi a formulát. A same padding nem azonos automatikusan a szimmetrikus paddinggel: páratlan szükséges teljes padding esetén a minimális megoldás aszimmetrikus lehet.

14.1.11 Következő alkalmazás

A 14.2. Több bemeneti és kimeneti csatorna egység a több bemeneti és kimeneti csatorna összegzési szerkezetét vizsgálja; az itteni térbeli alakzatok adják a csatornánkénti kimeneti mátrixok méretét és a paraméterszám számításának geometriai alapját.

14.1.12 Források