Budowanie modelu Resnet-34 za pomocą Pytorcha – przewodnik dla początkujących

Węzeł źródłowy: 1075632

Ten artykuł został opublikowany jako część Blogathon Data Science

Wprowadzenie

Głęboka nauka bardzo ewoluowała w ostatnich latach i wszyscy jesteśmy podekscytowani budowaniem głębszych sieci architektonicznych, aby uzyskać większą dokładność naszych modeli. Techniki te są szeroko wypróbowywane w pracach związanych z obrazami, takich jak klasyfikacja, klastrowanie lub synteza. Wchodzenie w głąb może wyglądać fajnie, ale nie pomoże, ponieważ sieci neuronowe borykają się z problemem zwanym degradacją.

W dużym stopniu wpływa to na dokładność. Prowadzi to również do problemu zwanego Znikającym spadkiem gradientu. To nie pozwoli nam poprawnie zaktualizować wagi podczas kroku wstecznej propagacji. Podczas kroku wstecznej propagacji stosujemy regułę łańcucha, pochodne każdej warstwy w miarę przechodzenia w dół sieci są mnożone.

Jeśli użyjemy głębszych warstw i mamy ukryte warstwy, takie jak sigmoid, pochodne zostaną zmniejszone poniżej 0.25 w każdej warstwie. Tak więc, gdy wiele pochodnych warstw jest mnożonych, gradient maleje wykładniczo i otrzymujemy bardzo małą wartość, która jest bezużyteczna przy obliczaniu gradientu. Doprowadziło to do stworzenia Resnetu przez Microsoft Research, który wykorzystywał pominięte połączenia, aby uniknąć degradacji. W tym artykule omówimy implementację 34 warstwowej architektury ResNet przy użyciu frameworka Pytorch w Pythonie.

znikający problem gradientu Resnet-34
1 Obraz

Jak omówiono powyżej, ten diagram pokazuje nam problem znikającego gradientu. Pochodne funkcji sigmoidalnych są skalowane poniżej 0.25, co powoduje utratę wielu informacji podczas aktualizacji gradientów.

Problem z sieciami samolotowymi

problem ze zwykłymi sieciami
2 Obraz

Jak pokazano na rysunku, widzimy sieci płaszczyzn, które mają głębsze warstwy. Po lewej stronie mamy błąd pociągu, a po prawej błąd testu. Sądzilibyśmy, że może to być pozew o nadmierne dopasowanie, ale tutaj % błędu sieci 56-warstwowej jest znacznie najgorszy zarówno w przypadku uczenia, jak i danych testowych, co nie ma miejsca, gdy model jest przesadnie dopasowany. Nazywa się to degradacją.

Architektura Resnet-34

Architektura Resnet-34
3 Obraz

Początkowo mamy warstwę splotową, która ma 64 filtry o rozmiarze jądra 7×7, to jest pierwszy zwój, następnie następuje warstwa maksymalnej puli. Mamy krok określony jako 2 w obu przypadkach. Następnie w konw2_x mamy warstwę puli i kolejne warstwy splotu. Warstwy te są zwykle pogrupowane w pary ze względu na sposób połączenia reszt (strzałki pokazują, że przeskakują co dwie warstwy).

Tutaj mamy 2 warstwy, które mają kernel_size 3×3, num_filters 64, a wszystko to powtarza się x3, co odpowiada warstwom między pulą,/2 a filtrem 128, w sumie 6 warstw (jedna pary razy 3). Te 2 warstwy mają rozmiar kernel_size 3×3, num_filters to 128, i one również są powtarzane, ale w tym czasie 4. Trwa to aż do avg_pooling i funkcji softmax. Za każdym razem, gdy liczba filtrów podwaja się, widzimy, jak określa pierwsza warstwa liczba_filtrów/2.

Kod do definiowania Resnet-34 w Pythonie:

class ResNet34(nn.Module): def __init__(self): super(ResNet34,self).__init__() self.block1 = nn.Sequential( nn.Conv2d(1,64,kernel_size=2,stride=2,padding= 3,bias=False), nn.BatchNorm2d(64), nn.ReLU(True) ) self.block2 = nn.Sequential( nn.MaxPool2d(1,1), ResidualBlock(64,64), ResidualBlock(64,64,2 ,3) ) self.block64,128 = nn.Sequential( ResidualBlock(128,128,2), ResidualBlock(4) ) self.block128,256 = nn.Sequential( ResidualBlock(256,256,2), ResidualBlock(5) ) self.block256,512 = nn. Sequential( ResidualBlock(512,512,2), ResidualBlock(2) ) self.avgpool = nn.AvgPool2d(1) # samogłoska_diacritic self.fc512,11 = nn.Linear(2) # grapheme_root self.fc512,168 = nn.Linear(3) # consonant_diacritic self.fc512,7 = nn.Linear(1) def forward(self,x): x = self.block2(x) x = self.block3(x) x = self.block4(x) x = self. blok5(x) x = self.block0(x) x = self.avgpool(x) x = x.view(x.size(1),-1) x1 = self.fc2(x) x2 = self.fc3( x) x3 = self.fc1(x) zwraca x2,x3,xXNUMX

Ten kod daje nam kompletną implementację modułu dla Resnet-34. Teraz zagłębmy się w zrozumienie, jak działa każda linia. W tym celu skróćmy architekturę, którą widzieliśmy wcześniej. Zobacz 34 schematy warstwowe poniżej.

wyjście kodu
4 Obraz

Widzimy, że musimy zaimplementować dowolną architekturę Resnet w 5 blokach. Pierwszy blok ma 64 filtry z krokiem 2., po którym następuje maksymalne łączenie z krokiem 2. Architektura wykorzystuje dopełnienie 3. Ponieważ istnieje możliwość wewnętrznego przesunięcia współzmiennej, musimy ustabilizować sieć poprzez normalizację wsadową. Na koniec używamy aktywacji ReLU. Pierwszy blok jest taki sam dla każdej architektury, a pozostałe bloki są zmieniane dla różnych warstw i powtarzane według określonego wzorca. Pierwszy blok można zaimplementować jako:

nn.Conv2d(1,64,kernel_size=2,stride=2,padding=3,bias=False),
nn.BatchNorm2d(64),
nn.ReLU(True)

W tym momencie mamy połączenie pomijania. Co jest główną ideą sieci szczątkowych. Diagram architektury, który widzieliśmy wcześniej, pokazywał pominięte połączenia za pomocą kropkowanych i ciemnych strzałek. Linia przerywana jest tym, co dzieje się tutaj, gdy przechodzimy do kanału o większym rozmiarze niż poprzedni. Drugi blok ma implementację początkowej maksymalnej puli 1 * 1 z rozmiarem jądra 3 * 3 i dwoma pozostałymi blokami, jak pokazano w poniższym kodzie. Te dwa przyjmują 64 jako kanały wejściowe i wyjściowe i są powtarzane 3 razy, jak pokazano na architekturze. W końcu ostatni jest połączony z następnym blokiem krokiem 2.

nn.MaxPool2d(1,1),ResidualBlock(64,64),ResidualBlock(64,64,2)

Zawartość ostatniego bloku została powtórzona 3 razy i wskazaliśmy, że ciemna strzałka na schemacie architektury i rozmiar kanału wejściowego i wyjściowego pozostają takie same. '/2' pokazane na diagramie architektury mówi nam o użytym kroku.

Trzeci blok przyjmuje rozmiar jądra 3 * 3 z kanałem wejściowym pochodzącym z ostatniego bloku 64 i dając kanał wyjściowy 128. Następnie bierzemy to samo 128 jako wejście i 128 jako kanał wyjściowy. Powtarzamy to 4 razy, jak pokazano na wcześniejszym schemacie architektury.

ResidualBlock(64,128), ResidualBlock(128,128,2)

Podobnie do tego, budujemy nasz czwarty i piąty blok, które mają 4 i 5 jako rozmiary jądra.

ResidualBlock(128,256), ResidualBlock(256,256,2)
ResidualBlock(256,512), ResidualBlock(512,512,2)

Funkcje liniowe pomagają ostatecznie połączyć to z misją końcową, która może obejmować kroki, takie jak klasyfikowanie zestawów danych cifar 10 itp., Ideą jest spłaszczenie warstw i podanie wartości probabilistycznej, aby znaleźć maksimum. I funkcja forward, którą zdefiniowaliśmy, aby połączyć każdy z bloków. Aby uzyskać pełną implementację Pythona, w tym szkolenie, możesz odnieść się do tego . Możemy również skorzystać z techniki uczenia transferu Pytorch, a dla tego kodu możesz odwołać się do tego GitHub repo.

Wnioski:

Numer referencyjny:

  1. https://www.kaggle.com/khoongweihao/resnet-34-pytorch-starter-kit
  2. https://datascience.stackexchange.com/questions/33022/how-to-interpert-resnet50-layer-types

O mnie: Jestem studentem naukowym zainteresowanym dziedziną Deep Learning i Przetwarzania Języka Naturalnego, a obecnie kończę studia podyplomowe w zakresie Sztucznej Inteligencji.

Image Source

  1. Obraz 1,2: https://towardsdatascience.com/the-vanishing-gradient-problem-69bf08b15484
  2. Obraz 3,4: https://datascience.stackexchange.com/questions/33022/how-to-interpert-resnet50-layer-types
  3. Obraz podglądu: https://www.zdnet.com/pictures/10-cool-robots-at-this-years-robobusiness-conference/2/

Zapraszam do kontaktu ze mną na:

  1. Linkedin: https://www.linkedin.com/in/siddharth-m-426a9614a/
  2. Github: https://github.com/Siddharth1698

Media pokazane w tym artykule na ResNet-34 nie są własnością Analytics Vidhya i są wykorzystywane według uznania Autora.

Źródło: https://www.analyticsvidhya.com/blog/2021/09/building-resnet-34-model-using-pytorch-a-guide-for-beginners/

Znak czasu:

Więcej z Analityka Widhja