Ebben az alfejezetben a ConvNeXt-család [P11] alapgondolatát vizsgáljuk: egy korábbi, jól ismert CNN-architektúrát fokozatosan modernizálunk a vision transformer korszakában megszokott építőelemekkel és tanítási recepttel, miközben a modell továbbra is konvolúciós háló marad. A cél nem egy konkrét modellváltozat betanítása, hanem a recept és az architektúra fogalmának szétválasztása. Előismeret: a 19.3. EfficientNet és architektúraskálázás skálázási tengelyei, a 18.4. Reziduális blokk ablatív vizsgálata reziduális blokk és ablatív protokoll, valamint a 15.4. Független gradiensellenőrzési protokoll numerikus ellenőrzés gondolata. A 7.4. Numerikus stabilitás és jelentésmegőrző implementáció numerikus stabilitási eredményeire csak annyiban támaszkodunk, hogy a labor normálásait stabilan implementáljuk.
Induló kérdés: ha egy 2015-ös stílusú ResNet-50-szerű hálót változatlanul hagyunk, de a modern transformer-recepttel tanítjuk, mi változik? És ha csak egyetlen építőelemet cserélünk le, hogyan tudjuk eldönteni, hogy a javulás az új elemtől vagy a megváltozott recepttől származik?
Definíció (architektúra). Egy konvolúciós háló architektúrájának nevezzük mindazokat a döntéseket, amelyek a forward függvényt írják le: a rétegek sorrendje, a kernelméretek, stride-ok, paddingek, csatornaszámok, aktivációk, normalizálások, skip-kapcsolatok és downsampling-rétegek. Az architektúra a paraméterek terét és a függvényosztályt határozza meg.
Definíció (tanítási recept, training recipe). A recept mindaz, ami a paraméterek keresését vezérli, de nem változtatja meg a forward függvényt: az optimalizáló (például AdamW a 6.4. Momentum és adaptív optimizálók szerint), a learning rate és annak ütemezése, a weight decay, az epochok száma, a batch méret, az augmentáció, a label smoothing, a stochastic depth, a keverési (mixup) stratégia, valamint az inicializálás és a kiértékelési protokoll.
A két fogalom azért kritikus, mert egy architektúra teljesítményét soha nem a recepttől függetlenül mérjük. A [P11] absztraktja szerint a munka egy standard ResNet-50-et modernizál fokozatosan, és a lépések között a tanítási recept cseréje is szerepel. A jelen kéziratban az absztrakt szintjén ellenőrzött állításokat idézzük; a pontos lépésenkénti eredményekhez a cikk teljes kísérleti szakasza szükséges.
Heurisztika (recept-architektúra szétválasztás). Ha egy új blokk bevezetésekor a baseline-t régi, az új modellt pedig új recepttel tanítjuk, akkor a mért különbség nem tulajdonítható egyetlen tényezőnek. A tisztességes összehasonlítás matched recipe-t igényel: mindkét modellt ugyanazzal a protokollal tanítjuk, és csak a vizsgált architekturális elemet változtatjuk. Ez ugyanaz az ablatív elv, amelyet a 18.4. Reziduális blokk ablatív vizsgálata egységben a skip-kapcsolatra bevezettünk.
A ConvNeXt-blokk a [P11] által vizsgált modernizálási lépésekből áll össze. A következő blokk a szakirodalomban ConvNeXt-blokk néven ismert sorrendet követi; a konkrét modellváltozat részletei a forrás szerinti konfigurációtól függhetnek.
Legyen a batchelt bemenet
,
ahol
a csatornaszám,
a térbeli méret. Legyen
a depthwise konvolúció súlya, azaz a PyTorch
nn.Conv2d(dim, dim, kernel_size=k, padding=p, groups=dim, bias=False)
réteg súlyalakja
a [D10] szerint; itt
és a kimeneti csatornák száma is
.
A depthwise réteg kimenete
ahol a szimmetrikus zero padding, és a kényelem kedvéért stride ; a kimeneti méret ekkor , ha .
Legyen a csatornadimenzióra vonatkozó LayerNorm: minden pozícióban a hosszúságú vektort normalizáljuk,
A itt a csatornadimenzió menti átlag és variancia, nem a mini-batch statisztika; ez a döntés eltér a BatchNorm 18.2. Batch normalization train és eval módban alfejezetben tárgyalt train/eval állapotkezelésétől. Legyen az expand arány, a GELU aktiváció, és két 1×1 konvolúció (bias nélkül), végül a LayerScale csatornánkénti szorzója. A blokk:
A itt csatornánkénti, térben broadcastolt szorzás. A kifejezés dimenzióellenőrzése: alakja ; a depthwise kimenete ; ugyanekkora; kimenete ; a GELU ezt őrzi meg; visszavetíti -re; a -szorzás és a reziduális összeadás ugyanebben a térben marad. A skip tehát akkor identitás, ha a térbeli méret és a csatornaszám nem változik; downsampling esetén külön shortcut szükséges.
Figyeljünk a különbségre a 19.2. MobileNet és inverted residual MobileNetV2 inverted residual blokkjához képest: ott a depthwise konvolúció a kiterjesztett, széles csatornatérben futott. Itt a depthwise réteg a keskeny csatornán kever térben, és az 1×1 rétegek végzik a csatornák keverését. A „large kernel” döntés azt jelenti, hogy a depthwise kernel tipikusan 7×7-es is lehet, mert a költsége arányú, nem .
A blokk költségmodelljét explicit feltevésekkel vezetjük le. Feltesszük: stride 1, szimmetrikus padding, így , ; a konvolúciós MAC-ot számoljuk, a GELU és LayerNorm szorzásait itt nem. A depthwise réteg MAC-igénye , mert minden kimeneti pixelre csatornánként szorzás-összeadás jut. Az első 1×1 réteg , a második MAC. Összesen:
A paraméterszám bias nélkül: a depthwise súly , a két 1×1 súly , a LayerNorm együtt , a LayerScale ; így
Példa: legyen , , , , , . A MAC-összeg:
A paraméterszám: . Az alakellenőrzés: bemenet , kimenet ugyanekkora, mert és stride 1.
A példa mutatja a depthwise döntés hatását: ha a kernelt közönséges, csoportú konvolúcióként használnánk, a súly alakja lenne, paraméterrel, és a MAC lenne csak a térbeli rétegben. A csoportosítás tehát a paraméter- és műveletszámot is csökkenti, de a kapacitást is korlátozza; ez heurisztikus kompromisszum, nem automatikus pontossági garancia.
A levezetési kötelezettség itt nem egy tétel, hanem egy kísérleti állítás feltételeinek pontos rögzítése. Mivel a [P11] forrásstátusza „arXiv-rekord és absztrakt ellenőrizve”, a részletes módszertani állításokhoz a cikk releváns szakaszainak olvasása szükséges. Amit az absztrakt szintjén rögzíthetünk:
Amit egy pontos reprodukcióhoz rögzíteni kell, de a jelen kézirati státusz mellett nem idézünk:
A cikk absztraktjának állítását idézni csak azzal a korláttal szabad, hogy a kísérleti táblázatok részletei nem ellenőrzöttek ebben a kéziratban. A fejezet ezért nem tesz a cikkben szereplő kísérleti táblázatokból származó, itt nem igazolt számszerű állítást.
A labor célja egy kisméretű, ConvNeXt-szerű blokk implementálása a
GlyphLab méretosztályában, benchmark-szám kitalálása nélkül. A következő
kód e kéziratban jelölt implementáció; az alak- és paraméterellenőrzést
a fenti kézi számítással vetjük össze. Futtatás a lab/
munkakönyvtárból:
cd /path/to/lab
python n076_mini_block.pyimport torch
import torch.nn as nn
torch.manual_seed(20261020)
device = torch.device("cpu")
class MiniConvNeXtBlock(nn.Module):
"""Kisméretű ConvNeXt-szerű blokk, bias nélküli konvolúciókkal.
Alak: (N,C,H,W) -> (N,C,H,W), stride=1, szimmetrikus padding.
"""
def __init__(self, dim, expand, kernel):
super().__init__()
assert kernel % 2 == 1, "a szimmetrikus paddinghez páratlan kernel kell"
pad = kernel // 2
self.dw = nn.Conv2d(dim, dim, kernel_size=kernel,
padding=pad, groups=dim, bias=False)
self.norm = nn.LayerNorm(dim) # NHWC-ben a csatornadimenzióra
self.pw1 = nn.Conv2d(dim, dim * expand, kernel_size=1, bias=False)
self.act = nn.GELU()
self.pw2 = nn.Conv2d(dim * expand, dim, kernel_size=1, bias=False)
self.gamma = nn.Parameter(torch.ones(dim, 1, 1))
def forward(self, x):
h = self.dw(x) # (N,C,H,W)
N, C, H, W = h.shape
h = h.permute(0, 2, 3, 1) # NHWC
h = self.norm(h) # (N,H,W,C)
h = h.permute(0, 3, 1, 2) # NCHW
h = self.pw1(h)
h = self.act(h)
h = self.pw2(h)
h = h * self.gamma
return x + h
model = MiniConvNeXtBlock(dim=2, expand=4, kernel=5).to(device).to(torch.float32)
x = torch.randn(1, 2, 8, 8, device=device, dtype=torch.float32)
y = model(x)
weight = model.dw.weight
print("dw weight shape:", tuple(weight.shape)) # elvárt: (2,1,5,5)
print("output shape:", tuple(y.shape)) # elvárt: (1,2,8,8)
n_params = sum(p.numel() for p in model.parameters())
print("params:", n_params, "expected:", 88)
print("norm type:", type(model.norm).__name__,
"| gamma shape:", tuple(model.gamma.shape))A kód ellenőrzései: a depthwise súly alakja
,
mert groups=2; a kimeneti alak
;
az összesített paraméterszám 88. A nn.LayerNorm(dim) a
permutálás után az NHWC utolsó dimenziójára, vagyis a csatornákra
normalizál. A seed a súlyok reprodukálhatóságát szolgálja, de a
számított kontroll a seedtől független.
A labor második része egy részletes ablatív terv, amelyet a jövőben futtatni lehet. Kérdés: a depthwise kernel mérete (3×3, 5×5, 7×7) hogyan hat a GlyphLab-pontosságra, ha minden más rögzített? Modell: patchify stem 4×4-es, stride 4 konvolúcióval 24×24→6×6, , két mini blokk, global average pooling, lineáris fej 3 osztályra. Változó tényező: csak a depthwise kernel mérete, a padding mindig a méretmegtartáshoz illesztett. Rögzített recept: AdamW, learning rate , weight decay , 50 epoch, batch 32, seed 20261020, a GlyphLab train/val splitje; a legjobb checkpoint kiválasztása kizárólag val loss alapján. Metrika: val accuracy; a tesztet csak a protokoll végén értékeljük. Erőforrás: CPU. A terv nem a [P11] reprodukciója; a GlyphLab 360 képe és 24×24 felbontása más tartomány, ezért a nagy kernel előnye nem vihető át automatikusan.
F1 (fogalmi, nehézség 1). Magyarázza el saját szavaival, mi a különbség a tanítási recept és az architektúra között, és adjon egy konkrét példát arra, hogy két azonos architektúra eltérő recepttel más tanulási görbét adhat.
F2 (levezetési, nehézség 2). Legyen , , , , , stride 1, szimmetrikus padding. Számítsa ki a blokk MAC-összegét és paraméterszámát bias nélkül. Ellenőrizze a dimenziókat a depthwise réteg súlyán.
F3 (implementációs, nehézség 2). Futtassa a fenti
labor kódot, majd módosítsa úgy, hogy dim=8,
expand=4, kernel=7, bemenet
.
Ellenőrizze, hogy a kimeneti alak
,
és adja meg a paraméterszámot az itteni képlettel is.
F4 (hibakeresési, nehézség 2). Az alábbi kódrészletben a depthwise réteg definíciója hibás:
self.dw = nn.Conv2d(dim, dim, kernel_size=5, padding=2, bias=False)Mi a hiba? Milyen következménnyel jár a paraméterszámra és a blokk szándékolt számítási szerkezetére nézve? Adja meg a javítást, és írja le a visszaellenőrzéshez használt súlyalakot.
F5 (kísérleti/transzfer, nehézség 3). Tervezzen matched-recipe ablatív kísérletet a GlyphLab adaton a normalizálás típusának (BatchNorm2d a csatornadimenzióra versus LayerNorm a csatornadimenzióra) összehasonlítására. Adja meg a protokollt: modell, split, baseline, változó tényező, rögzített tényezők, metrika, erőforrás és az érvényességi korlát. Nem kell futtatást végeznie; a tervnek ellenőrizhetőnek kell lennie.
F1. Az architektúra a forward függvényt rögzíti: rétegek, kernelméretek, csatornaszámok, skip-kapcsolatok. A recept a paraméterkeresés protokollja: optimalizáló, ütemezés, augmentáció, regularizálás, epochszám. Példa: ugyanaz a háromrétegű MLP AdamW-vel, 100 epochig tanítva, és SGD-vel, rögzített tanulási rátával, 10 epochig tanítva, eltérő tanulási görbét ad; az architektúra azonos, tehát a különbség a receptből származik. Ellenpéldával igazolható a szétválasztás szükségessége: ha a baseline-t régi, az új modellt új recepttel vetjük össze, a hatás nem egyértelműen tulajdonítható az architektúrának.
F2. Adatok: , , , , . A szimmetrikus padding , így a kimenet . MAC:
A paraméterszám: . A depthwise súly alakja , mert ; a két 1×1 súly és . A GELU és a LayerNorm nem változtatja az alakot. A broadcast szorzás a tenzorral érvényes, mert a csatornadimenzió az első.
F3. A módosított labor kódban
dim=8, expand=4, kernel=7, padding 7//2=3,
bemenet
.
A depthwise kimenet
,
tehát a kimeneti alak
.
A súlyalak
.
A képlet szerint a paraméterszám
.
A kódban sum(p.numel() for p in model.parameters()) ezzel
egyezik. Numerikus tolerancia itt nem szükséges, mert egész számok;
shape-ellenőrzés a futtatás kimenetében.
F4. A hiba: a groups argumentum hiánya,
ezért a réteg közönséges konvolúció lesz, groups=1. A súly
alakja ekkor
lenne dim=5 esetén, általában
,
nem pedig a szándékolt
.
Következmény: a paraméterszám
lesz
helyett, a MAC
lesz, és a blokk nem depthwise separable. A javítás:
groups=dim. Visszaellenőrzés:
model.dw.weight.shape értéke (dim, 1, 5, 5),
és a params visszatér a kézi képlettel számolt értékre.
F5. Egy lehetséges terv. Modell: patchify stem 4×4
stride 4, 8 csatorna, két blokk, GAP, lineáris fej 3 osztályra. A blokk
norm rétege a változó tényező: vagy nn.BatchNorm2d(8) a
depthwise után közvetlenül a NCHW tenzoron, vagy
nn.LayerNorm(8) NHWC permutálással. Baseline:
BatchNorm-változat, mert a klasszikus CNN-recepthez ez közelebb áll.
Rögzített: AdamW, LR
,
wd
,
50 epoch, batch 32, seed 20261020, azonos train/val split, legjobb
checkpoint val loss alapján. Metrika: val accuracy; a tesztet egyszer, a
protokoll végén értékeljük. Megfigyelési egység: scene_id, a bootstrapot
is jelenet-szinten végezzük 5.4. Függő képek, seedek
és resampling szerint. Erőforrás: CPU. Érvényességi korlát: egy
seed, 360 kép, 24×24 felbontás; az eredmény nem általánosítható nagyobb
adatra, és a BN train/eval állapotkülönbségét a kiértékelésnél be kell
tartani 18.2. Batch normalization train és eval
módban. A negatív eredmény is elfogadható.
A leggyakoribb tévedés: a „korszerű” vagy „modern” címkét örök teljesítményrangsorként kezelni. A ConvNeXt-blokk előnye a [P11] vizsgálati feltételei mellett értelmezendő; e feltételek nélkül az állítás nem vihető át. Ellenpélda heurisztikaként: a 360 képes GlyphLab adaton egy nagy, 7×7 depthwise kernelt használó modern blokk több paraméterrel és nagyobb recepciós mezővel túl is illeszkedhet, miközben egy egyszerű, 3×3-as CNN jobb tesztpontosságot ér el. Ez nem mért eredmény, hanem címkézett gondolatkísérlet; éppen azt mutatja, hogy az adat mérete és a benchmark környezete része az állításnak. Önellenőrzés: minden képletben ellenőriztük a csoportos konvolúció súlyalakját, a szimmetrikus padding képletét és a reziduális összeadás broadcastját. Visszahívás: a 18.4. Reziduális blokk ablatív vizsgálata matched-recipe elve adja az ablatív kontroll alapját, a 15.4. Független gradiensellenőrzési protokoll numerikus ellenőrzés arra emlékeztet, hogy a kód egyezése nem bizonyítja a modell optimalitását, a 7.4. Numerikus stabilitás és jelentésmegőrző implementáció stabil normálás pedig a LayerNorm implementációjánál releváns.
A ConvNeXt-példa azt mutatja, hogy a CNN-architektúra modernizálása és a tanítási recept cseréje két külön döntési szint, amelyet matched-recept ablációval lehet szétválasztani. A formális blokk depthwise nagy kernelt, csatorna-LayerNormot, GELU-t, 1×1 expand/project rétegeket és reziduális skipet kombinál; költsége MAC és paraméter. A [P11] kísérleti feltételeit csak absztrakt szinten idéztük, a részletes protokoll ellenőrzésre szorul. A labor egy 88 paraméteres mini blokk alak- és paraméterellenőrzését, valamint kernelméret-ablatív tervet ad benchmark-szám nélkül. A „modern” címke nem örök rangsor, hanem adott adat- és receptfeltételekhez kötött állítás.
A következő 20.1. Feature extractor és új fej egység a transzfertanulást kezdi: ott azt vizsgáljuk, hogy egy korszerű CNN-blokkból épített modell súlyait mikor és hogyan lehet más adatra átvinni. Az itteni recept-architektúra szétválasztás közvetlenül szükséges lesz, mert az előtanított modell és az új fej tanítása különböző protokollt igényel.