18.1 Reziduális blokk és identitásút

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

Ez az alfejezet a reziduális blokkot, a mély hálózatok egyik legfontosabb szerkezeti elemét vezeti be. Az előismeret a 11.4. Egy teljes PyTorch tanítási iteráció alfejezetből a teljes tanítási lépés, a 14.4. Csoportos és depthwise konvolúció alfejezetből a csatornák közti kapcsolat korlátozása, a 16.4. IV. ellenőrző pont: a CNN-operátor teljes megértése alfejezetből a CNN-operátor specifikációja, a 17.4. Architektúra összehasonlítása kontrollált keretben alfejezetből pedig a kontrollált architektúra-összehasonlítás fogalma. A korábbi 17.1. LeNet és a lokális megosztott reprezentáció megmutatta, hogy a rétegek egymásra építése önmagában nem feltétlenül hoz jobb eredményt: a mélység növelése új optimalizálási és numerikus nehézségeket teremt. He, Zhang, Ren és Sun P06 3.1–3.2 szakasza a reziduális tanulást olyan blokkal vezeti be, amelyben a háló nem közvetlenül a kívánt leképezést, hanem annak egy eltérését tanulja egy identitásút mellett.

Induló kérdés: ha egy blokk kimenete y=x+F(x)y=x+F(x), akkor mit tudunk mondani a blokk Jacobi-mátrixáról, és miért nem következik ebből, hogy minden reziduális háló jól kondicionált?

18.1.2 Definíció és intuíció

Legyen a blokk bemenete xx. A reziduális blokk kimenete

y=x+F(x;θ), y = x + F(x;\theta),

ahol FF a reziduális leképezés: általában két vagy három konvolúciós réteg, amelyet nemlinearitás és esetleg normalizálás követ, θ\theta pedig a tanulandó paraméterek összessége. Az xx-et közvetlenül a kimenethez vezető utat identity shortcutnak vagy identitásútnak nevezzük. Az intuíció az, hogy ha a kívánt blokk kimenet közel van a bemenethez, akkor a hálónak elegendő F(x)≈0F(x)\approx 0-t tanulnia; a shortcut így egy előre adott, paramétermentes jelölt leképezést biztosít.

A tenzoralakú változatban x∈ℝCin×H×Wx\in\mathbb R^{C_{in}\times H\times W}, F(x)∈ℝCout×Hout×WoutF(x)\in\mathbb R^{C_{out}\times H_{out}\times W_{out}}. Az összeadás csak akkor értelmes, ha

Cin=Cout,H=Hout,W=Wout. C_{in}=C_{out},\qquad H=H_{out},\qquad W=W_{out}.

Ha a blokk csatornát vált, vagy s>1s>1 stride-dal csökkenti a térbeli méretet, akkor a shortcutot is transzformálni kell. A projection shortcut egy 1×11\times1-es konvolúcióval,

h(x)=Wsx, h(x)=W_s x,

ahol Ws∈ℝCout×Cin×1×1W_s\in\mathbb R^{C_{out}\times C_{in}\times 1\times 1} és a stride megegyezik a főág stride-jával, így a kimenet

y=F(x;θ)+Wsx. y = F(x;\theta) + W_s x.

A WsW_s projekció tehát nem egyszerű dimenziótoldás, hanem tanulható lineáris leképezés, amely a shortcut út és a főág alakját összehangolja a 14.1. Stride, padding, dilation és outputméret alfejezetben levezetett kimeneti méret szerint.

A P06 megkülönbözteti a basic blokkot és a bottleneck blokkot. A basic blokk két 3×33\times3-as konvolúcióból áll, változatlan csatornaszámmal. A bottleneck blokk három rétegből épül fel: egy 1×11\times1-es konvolúció csökkenti a csatornákat CC-ről dd-re, egy 3×33\times3-as konvolúció a szűkebb dd csatornán dolgozik, majd egy második 1×11\times1-es konvolúció visszaállítja a CC csatornát. A tipikus C=256C=256, d=64d=64 választás mellett a paraméterszám bias nélkül:

Réteg Csatorna Kernel Paraméter (bias nélkül)
1. konvolúció 256→64256\to64 1×11\times1 256⋅64=16384256\cdot64=16\,384
2. konvolúció 64→6464\to64 3×33\times3 64⋅64⋅9=3686464\cdot64\cdot9=36\,864
3. konvolúció 64→25664\to256 1×11\times1 64⋅256=1638464\cdot256=16\,384

Összesen 6963269\,632 paraméter. Két közvetlen 3×33\times3-as konvolúció 256256 csatornán ezzel szemben 2⋅256⋅256⋅9=11796482\cdot256\cdot256\cdot9=1\,179\,648 paramétert igényelne, tehát a bottleneck körülbelül tizenhetedére csökkenti a paraméterszámot, miközben a bemeneti és kimeneti csatornaszám változatlan marad.

18.1.3 A lokális Jacobi-alak levezetése

A központi állítást absztrakt vektoros formában mondjuk ki. Legyen x∈ℝdx\in\mathbb R^d a blokk bemenete, F:ℝd→ℝdF:\mathbb R^d\to\mathbb R^d a reziduális leképezés, és y=x+F(x)y=x+F(x).

Lemma (lokális Jacobi-alak). Ha FF differenciálható az xx pontban, akkor a G(x)=x+F(x)G(x)=x+F(x) leképezés Jacobi-mátrixa ugyanabban a pontban

JG(x)=Id+JF(x), J_G(x) = I_d + J_F(x),

ahol Id∈ℝd×dI_d\in\mathbb R^{d\times d} az egységmátrix, JF(x)∈ℝd×dJ_F(x)\in\mathbb R^{d\times d} pedig FF Jacobi-mátrixa a könyv 4.3. Jacobi-mátrix, láncszabály és VJP konvenciója szerint: a JFJ_F ii. sora és jj. oszlopa ∂Fi/∂xj\partial F_i/\partial x_j.

Bizonyítás. A GG leképezés ii. koordinátája Gi(x)=xi+Fi(x)G_i(x)=x_i+F_i(x). A parciális deriváltra minden i,j∈{1,…,d}i,j\in\{1,\dots,d\} esetén

∂Gi∂xj=∂xi∂xj+∂Fi∂xj=δij+∂Fi∂xj, \frac{\partial G_i}{\partial x_j} = \frac{\partial x_i}{\partial x_j} + \frac{\partial F_i}{\partial x_j} = \delta_{ij} + \frac{\partial F_i}{\partial x_j},

ahol δij=1\delta_{ij}=1, ha i=ji=j, egyébként 00. A jobb oldal első tagja az IdI_d egységmátrix (i,j)(i,j) eleme, a második pedig a JF(x)J_F(x) mátrix (i,j)(i,j) eleme. Ezzel a mátrixegyenlőséget koordinátánként beláttuk. ∎

A lemma következménye a visszaterjesztésre: ha a blokk kimenetére érkező upstream gradiens g=∇yLg=\nabla_y L, akkor a VJP-szabály szerint

∇xL=JG(x)⊤g=(Id+JF(x))⊤g=g+JF(x)⊤g. \nabla_x L = J_G(x)^\top g = (I_d+J_F(x))^\top g = g + J_F(x)^\top g.

Az első tag, gg, változatlanul átfolyik az identitásúton; a második tag a paraméterezett FF ágon keresztül visszaterjesztett gradiens. Ez a felbontás az, amit a szakirodalom gyakran „a gradiens az identitásúton is eljut a korábbi rétegekhez” formában említ.

Miért nem garantál ez minden hálón jó kondicionáltságot? A fenti lemma lokális állítás: egyetlen xx pontban írja le a blokk Jacobi-mátrixát. Egy mátrix kondíciószámát 2-es spektrális normában a κ2(M)=σmax(M)/σmin(M)\kappa_2(M)=\sigma_{\max}(M)/\sigma_{\min}(M) hányados adja. Az Id+JF(x)I_d+J_F(x) mátrix kondíciószáma tetszőlegesen nagy lehet, mert JF(x)J_F(x) sajátértékei a tanulás során közel kerülhetnek −1-1-hez. Szélsőséges lineáris ellenpéldaként legyen F(x)=−xF(x)=-x; ekkor y=0y=0, és

JG(x)=Id+(−Id)=0. J_G(x)=I_d+(-I_d)=0.

A Jacobi-mátrix szinguláris, a kondíciószám végtelen, annak ellenére, hogy a shortcut jelen van. A lineáris esetben persze κ2(Id+A)\kappa_2(I_d+A) korlátos marad, ha AA sajátértékei elkerülik a −1-1-et, de a nemlineáris FF Jacobi-mátrixa pontról pontra változik, ezért egyetlen pontban számított kondíciószám nem ad globális korlátot a teljes tanítási pályára.

Mély háló esetén a láncszabály tovább nehezíti a helyzetet. Ha a háló LL blokk kompozíciója, G=GL∘⋯∘G1G=G_L\circ\cdots\circ G_1, ahol Gk(xk)=xk+Fk(xk)G_k(x_k)=x_k+F_k(x_k), akkor

JG(x)=∏k=1L(Id+JFk(xk)), J_G(x) = \prod_{k=1}^{L} \left(I_d+J_{F_k}(x_k)\right),

ahol xkx_k a kk. blokk bemenete. Még ha minden egyes tényező adott pontban jól kondicionált is, a szorzat spektruma elfajulhat. Ha például minden tényező 0,5Id0{,}5I_d, akkor a szorzat 2−LId2^{-L}I_d: a kondíciószáma ugyan 1, de a gradiens normája exponenciálisan csillapodik. A skip tehát nem tünteti el a főág okozta csillapítást, csak hozzáad egy plusz utat. A P06 kísérleti javulást mutat, nem pedig kondicionáltsági vagy globális konvergenciatételt; az állítás típusa empirikus eredmény, nem matematikai garancia.

18.1.4 Kézi számpélda

Legyen a bemenet és a reziduális leképezés lineáris:

x=[3−1],F(x)=Ax+b,A=[0,50,20,1−0,3],b=[0,10,2]. x=\begin{bmatrix}3\\-1\end{bmatrix},\qquad F(x)=Ax+b,\qquad A=\begin{bmatrix}0{,}5 & 0{,}2\\0{,}1 & -0{,}3\end{bmatrix},\qquad b=\begin{bmatrix}0{,}1\\0{,}2\end{bmatrix}.

Először a reziduális ág:

F(x)=[0,5⋅3+0,2⋅(−1)0,1⋅3−0,3⋅(−1)]+[0,10,2]=[1,30,6]+[0,10,2]=[1,40,8]. F(x)= \begin{bmatrix}0{,}5\cdot 3+0{,}2\cdot(-1)\\0{,}1\cdot 3-0{,}3\cdot(-1)\end{bmatrix} + \begin{bmatrix}0{,}1\\0{,}2\end{bmatrix} = \begin{bmatrix}1{,}3\\0{,}6\end{bmatrix} + \begin{bmatrix}0{,}1\\0{,}2\end{bmatrix} = \begin{bmatrix}1{,}4\\0{,}8\end{bmatrix}.

A blokk kimenete

y=x+F(x)=[3−1]+[1,40,8]=[4,4−0,2]. y=x+F(x)= \begin{bmatrix}3\\-1\end{bmatrix} + \begin{bmatrix}1{,}4\\0{,}8\end{bmatrix} = \begin{bmatrix}4{,}4\\-0{,}2\end{bmatrix}.

A Jacobi-mátrix a lemma szerint

JG(x)=I2+A=[1001]+[0,50,20,1−0,3]=[1,50,20,10,7]. J_G(x)=I_2+A= \begin{bmatrix}1 & 0\\0 & 1\end{bmatrix} + \begin{bmatrix}0{,}5 & 0{,}2\\0{,}1 & -0{,}3\end{bmatrix} = \begin{bmatrix}1{,}5 & 0{,}2\\0{,}1 & 0{,}7\end{bmatrix}.

Ellenőrzésképpen a g=(1,2)⊤g=(1,2)^\top upstream gradienssel a VJP:

∇xL=JG(x)⊤g=[1,50,10,20,7][12]=[1,71,6]. \nabla_x L = J_G(x)^\top g = \begin{bmatrix}1{,}5 & 0{,}1\\0{,}2 & 0{,}7\end{bmatrix} \begin{bmatrix}1\\2\end{bmatrix} = \begin{bmatrix}1{,}7\\1{,}6\end{bmatrix}.

Ugyanez a felbontásból: az identitásút g=(1,2)⊤g=(1,2)^\top-t ad, a reziduális út pedig

A⊤g=[0,50,10,2−0,3][12]=[0,7−0,4], A^\top g= \begin{bmatrix}0{,}5 & 0{,}1\\0{,}2 & -0{,}3\end{bmatrix} \begin{bmatrix}1\\2\end{bmatrix} = \begin{bmatrix}0{,}7\\-0{,}4\end{bmatrix},

és (1,2)⊤+(0,7,−0,4)⊤=(1,7,1,6)⊤(1,2)^\top+(0{,}7,-0{,}4)^\top=(1{,}7,1{,}6)^\top, egyezésben a direkt számolással.

18.1.5 Labor: kis reziduális blokk

A labor a skip mechanizmust izolálja, ezért a BatchNormot elhagyjuk; a BN bevezetése a 18.2. Batch normalization train és eval módban feladata. Az alábbi lab/residual_block.py két blokkot valósít meg: azonos alakút és csatornát váltót. Az ellenőrzéshez a 16.4. IV. ellenőrző pont: a CNN-operátor teljes megértése alfejezetben megszokott háromszögelvet követjük: a képletezett y=x+F(x)y=x+F(x) összeadást közvetlenül összehasonlítjuk a blokk kimenetével.

Munkakönyvtár: lab/.

"""lab/residual_block.py"""
import torch
import torch.nn as nn

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


class BasicResBlock(nn.Module):
    """Azonos csatornaszámú, stride=1 reziduális blokk."""
    def __init__(self, C, kernel=3):
        super().__init__()
        self.conv1 = nn.Conv2d(C, C, kernel, padding=1)
        self.conv2 = nn.Conv2d(C, C, kernel, padding=1)
        self.relu = nn.ReLU()

    def forward(self, x):
        F = self.relu(self.conv1(x))
        F = self.conv2(F)
        return x + F


class ProjectionResBlock(nn.Module):
    """Csatornát váltó blokk 1x1 projekciós shortcuttal."""
    def __init__(self, C_in, C_out, stride=1):
        super().__init__()
        self.conv1 = nn.Conv2d(C_in, C_out, 3, stride=stride, padding=1)
        self.conv2 = nn.Conv2d(C_out, C_out, 3, padding=1)
        self.shortcut = nn.Conv2d(C_in, C_out, 1, stride=stride)
        self.relu = nn.ReLU()

    def forward(self, x):
        F = self.relu(self.conv1(x))
        F = self.conv2(F)
        return F + self.shortcut(x)


def main():
    N, C, H, W = 2, 3, 24, 24
    x = torch.randn(N, C, H, W, device=device, dtype=dtype)

    # Azonos alakú blokk: a kimenetnek x + F(x)-szel kell egyeznie.
    block_same = BasicResBlock(C).to(device, dtype)
    block_same.eval()
    with torch.no_grad():
        y = block_same(x)
        F_ref = block_same.conv2(block_same.relu(block_same.conv1(x)))
        err_same = (y - (F_ref + x)).abs().max().item()
    print("azonos alak max hiba:", err_same)

    # Csatornát váltó blokk: a shortcut 1x1 konvolúcióval projektál.
    block_proj = ProjectionResBlock(C, 6).to(device, dtype)
    block_proj.eval()
    with torch.no_grad():
        y2 = block_proj(x)
    print("projekcios kimenet alakja:", tuple(y2.shape))
    print("elvart alak: (2, 6, 24, 24)")


if __name__ == "__main__":
    main()

Futtatás a projekt gyökeréből:

python lab/residual_block.py

A várt kimenet szemléltetés, nem mért futás:

azonos alak max hiba: 0.0
projekcios kimenet alakja: (2, 6, 24, 24)
elvart alak: (2, 6, 24, 24)

Az első sor azt ellenőrzi, hogy a BasicResBlock valóban az y=x+F(x)y=x+F(x) összeadást számolja: a hiba float32 kerekítés mellett 00, a tűrés 10−610^{-6}. A második sor a csatornaváltó blokk kimeneti alakját ellenőrzi: Cin=3C_{in}=3-ból Cout=6C_{out}=6 lett, a térbeli méret 24×2424\times24 maradt, mert stride s=1s=1 és a 3×33\times3-as kernel p=1p=1 paddingje megőrzi a méretet, összhangban a 14.1. Stride, padding, dilation és outputméret formulájával:

Hout=⌊24+2⋅1−3−11⌋+1=24. H_{out}=\left\lfloor\frac{24+2\cdot1-3-1}{1}\right\rfloor+1=24.

A projekciós shortcut itt 1×11\times1-es konvolúció, amely a 33 csatornát 66-ra képezi le, így a főág és a shortcut alakja összeadhatóvá válik.

18.1.6 Feladatok

F1 (fogalmi, nehézség 1). Definiálja az identitás shortcutot és a projection shortcutot. Adjon egy konkrét bemeneti alakot, amelynél FF kimenete csatornát vált, és mondja meg, miért nem értelmes az x+F(x)x+F(x) összeadás projekció nélkül.

F2 (levezetési, nehézség 2). Legyen F(x)=Ax+bF(x)=Ax+b lineáris leképezés, A∈ℝ2×2A\in\mathbb R^{2\times2}. Bizonyítsa be a lemma alapján, hogy JG(x)=I2+AJ_G(x)=I_2+A, és adjon olyan konkrét AA mátrixot, amelyre κ2(I2+A)≥100\kappa_2(I_2+A)\ge100. Számolja ki a sajátértékeket vagy a szinguláris értékeket.

F3 (implementációs, nehézség 2). Implementáljon ProjectionResBlock stílusú blokkot Cin=1C_{in}=1, Cout=4C_{out}=4, 5×55\times5-ös kernel, p=2p=2, stride s=2s=2 mellett. Ellenőrizze a kimeneti alakot egy (2,1,24,24)(2,1,24,24) bemeneten, és a shortcut nélküli főággal való összehasonlítással a max hibát. Adja meg a futtatható kódot, a várt shape-et és a tűrést.

F4 (hibakeresési, nehézség 2). Az alábbi kód hibás:

class BrokenBlock(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(2, 4, 3, padding=1)
        self.conv2 = nn.Conv2d(4, 4, 3, padding=1)
        self.relu = nn.ReLU()

    def forward(self, x):
        return self.conv2(self.relu(self.conv1(x))) + x

Lokalizálja a hibát, magyarázza el a következményét, javítsa ki projekciós shortcuttal, és ellenőrizze a javítást egy (2,2,24,24)(2,2,24,24) bemeneten. Adja meg a hiba okát, a javított kódot és az ellenőrző futtatás eredményét.

F5 (kísérlettervezési, nehézség 3). Tervezzen kontrollált ablatív kísérletet a GlyphLab adaton, amely a skip út hatását méri az orientációosztályozási feladatra. Rögzítse a kérdést, a baseline-t, a spliteket, a paraméterkeretet, a választási szabályt, a metrikát, a seed-kezelést és az érvényességi korlátokat. Nincs előre megadott győztes; a 17.4. Architektúra összehasonlítása kontrollált keretben fair comparison keretét kövesse.

18.1.7 Megoldások és indoklás

F1 megoldása. Az identitás shortcut a y=x+F(x)y=x+F(x) képletben az xx közvetlen átvezetése a kimenethez, paraméter nélkül. Ez akkor megengedett, ha xx és F(x)F(x) alakja megegyezik. A projection shortcut h(x)=Wsxh(x)=W_sx tanulható lineáris transzformáció, amely a shortcut utat a főág alakjára hozza. Példa: x∈ℝ2×3×24×24x\in\mathbb R^{2\times3\times24\times24}, FF kimenete ℝ2×6×24×24\mathbb R^{2\times6\times24\times24}. Ekkor x+F(x)x+F(x) nem értelmezhető, mert a csatornadimenzió 3≠63\neq6; a PyTorch add művelet shape-mismatch hibát adna. A projection 1×11\times1-es konvolúcióval 3→63\to6 csatornát képez, így mindkét tag (2,6,24,24)(2,6,24,24) lesz.

F2 megoldása. A lemmából JG(x)=I2+JF(x)J_G(x)=I_2+J_F(x). Lineáris FF esetén JF(x)=AJ_F(x)=A minden xx-re, tehát JG(x)=I2+AJ_G(x)=I_2+A. Válasszuk a diagonális mátrixot

A=[−0,990099]. A=\begin{bmatrix}-0{,}99 & 0\\0 & 99\end{bmatrix}.

Ekkor

I2+A=[0,0100100]. I_2+A=\begin{bmatrix}0{,}01 & 0\\0 & 100\end{bmatrix}.

A szinguláris értékek diagonális mátrixnál a főátló elemeinek abszolút értékei: σ1=100\sigma_1=100, σ2=0,01\sigma_2=0{,}01, tehát

κ2(I2+A)=1000,01=104≥100. \kappa_2(I_2+A)=\frac{100}{0{,}01}=10^4\ge100.

Az ellenőrzés mutatja, hogy a shortcut jelenléte ellenére a Jacobi-mátrix tetszőlegesen rosszul kondicionált lehet, ha FF spektruma −1-1 közelébe kerül.

F3 megoldása. A kód:

"""lab/residual_stride.py"""
import torch
import torch.nn as nn

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


class StrideResBlock(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 4, 5, stride=2, padding=2)
        self.conv2 = nn.Conv2d(4, 4, 5, padding=2)
        self.shortcut = nn.Conv2d(1, 4, 1, stride=2)
        self.relu = nn.ReLU()

    def forward(self, x):
        F = self.relu(self.conv1(x))
        F = self.conv2(F)
        return F + self.shortcut(x)


def main():
    x = torch.randn(2, 1, 24, 24, device=device, dtype=dtype)
    block = StrideResBlock().to(device, dtype)
    block.eval()
    with torch.no_grad():
        y = block(x)
        F_ref = block.conv2(block.relu(block.conv1(x)))
        err = (y - (F_ref + block.shortcut(x))).abs().max().item()
    print("kimeneti alak:", tuple(y.shape))
    print("max hiba:", err)


if __name__ == "__main__":
    main()

A kimeneti méret a 14.1. Stride, padding, dilation és outputméret formulával: Hout=⌊(24+2⋅2−5−1)/2⌋+1=12H_{out}=\lfloor(24+2\cdot2-5-1)/2\rfloor+1=12, tehát a várt alak (2,4,12,12)(2,4,12,12). A shortcut 1×11\times1-es konvolúció stride s=2s=2-vel, így annak kimenete is (2,4,12,12)(2,4,12,12). A max hiba tűrése 10−610^{-6}; a várt érték 00.

F4 megoldása. A hiba oka: a BrokenBlock.forward az xx bemenetet közvetlenül adja hozzá a főág kimenetéhez, de xx csatornaszáma 22, a főág kimenetéé pedig 44. A + művelet PyTorchban shape-mismatch RuntimeError-t eredményez. A következmény az, hogy a blokk egyetlen forwardja sem fut le. Javítás: adjunk a konstruktorhoz egy 1×11\times1-es projekciós konvolúciót, és a forwardban azt használjuk:

class FixedBlock(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(2, 4, 3, padding=1)
        self.conv2 = nn.Conv2d(4, 4, 3, padding=1)
        self.shortcut = nn.Conv2d(2, 4, 1)
        self.relu = nn.ReLU()

    def forward(self, x):
        F = self.conv2(self.relu(self.conv1(x)))
        return F + self.shortcut(x)

Ellenőrzés (2,2,24,24)(2,2,24,24) bemeneten: a kimenet alakja (2,4,24,24)(2,4,24,24), és a (F + shortcut(x)) kifejezés közvetlen kiértékelésével a max hiba 00 a 10−610^{-6} tűrés mellett.

F5 megoldása. Egy lehetséges protokoll:

18.1.8 Tipikus tévedés ellenpéldával

A leggyakoribb tévedés az, hogy a skip út jelenlétét globális konvergenciabizonyításnak tekintik. A fenti lemma csak lokális Jacobi-azonosság, és a JFJ_F tetszőleges értéke miatt nem zárja ki a rossz kondicionáltságot. Konkrét ellenpélda: legyen F(x)=−xF(x)=-x. Ekkor a blokk kimenete y=x+F(x)=0y=x+F(x)=0 minden xx-re. A shortcut jelen van, a Jacobi mégis Id+(−Id)=0I_d+(-I_d)=0, tehát a blokk a bemenet minden információját eltünteti. Egy ilyen blokkokból álló háló bármely mélységben konstans nullát ad, így semmilyen értelmes feladatot nem tanul meg. A skip tehát csak egy lehetséges gradiensutat biztosít; a tényleges tanulási dinamika és a konvergencia továbbra is a nemlineáris optimalizálás tulajdonságaitól függ. A P06 empirikus javulást közöl, nem tételként bizonyított globális garanciát.

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

Önellenőrző kérdések: (1) Mikor értelmes az x+F(x)x+F(x) összeadás tenzoralakban? (2) Mi a projection shortcut szerepe csatornaváltásnál? (3) Igaz-e, hogy ha minden blokk Jacobija JG=Id+JFJ_G=I_d+J_F, akkor a teljes háló Jacobija IdI_d? (4) Mit ellenőriz a laborban a err_same érték? (5) Milyen állítástípus a P06 javulásra vonatkozó megállapítása?

Korábbi fogalmak visszahívása: a 6.1. Objektív, reguláris tag és gradienslépés alfejezetből a gradienslépés és a loss-átlag skálázása; a 11.4. Egy teljes PyTorch tanítási iteráció alfejezetből a zero_grad–forward–backward–step sorrend; a 14.1. Stride, padding, dilation és outputméret alfejezetből a kimeneti méret formulája; a 14.4. Csoportos és depthwise konvolúció alfejezetből a csoportos konvolúció csatornakorlátozása, amely a bottleneck 1×11\times1-es rétegeinél pontszerű, teljes csatornakapcsolatot jelent; a 16.4. IV. ellenőrző pont: a CNN-operátor teljes megértése alfejezetből az operátor-specifikáció háromszöge; a 17.4. Architektúra összehasonlítása kontrollált keretben alfejezetből pedig a fair comparison kerete. A BatchNorm, amely a teljes P06 blokkban a konvolúciók után áll, a következő egység témája.

18.1.10 Rövid összefoglaló

A reziduális blokk y=x+F(x)y=x+F(x) alakú, ahol a shortcut identitás vagy 1×11\times1-es projekció, ha az alak nem egyezik. A blokk Jacobi-mátrixa differenciálható FF esetén Id+JF(x)I_d+J_F(x), így a VJP-ben a gradiens az identitásúton és a reziduális ágon is terjed. Ez az azonosság lokális, és nem garantál globálisan jó kondicionáltságot: JFJ_F sajátértékei közel kerülhetnek −1-1-hez, a mély szorzat spektruma pedig akkor is elfajulhat, ha az egyes tényezők jól kondicionáltak. A labor két kis blokkot épít és ellenőriz. A BatchNorm-mechanizmus a következő egységben következik.

18.1.11 Következő alkalmazás

A 18.2. Batch normalization train és eval módban a BatchNorm tanítási és kiértékelési módját vezeti be a P07, P08 és D12 források alapján, és visszatér az itteni reziduális blokkra, amikor a normalizálást a főágba illeszti.

18.1.12 Források