ResNet: Pogromca Szklanego Sufitu

W skrócie: ResNet (Residual Network) to architektura, która pozwoliła nam przeskoczyć z sieci mających 20 warstw do takich, które mają ich ponad 1000. Bez ResNetu dzisiejsza technologia rozpoznawania obrazów (używana w medycynie czy Tesli) byłaby o dekadę do tyłu.

1. Dlaczego głębiej nie zawsze znaczyło lepiej?

W teorii, im więcej warstw ma sieć, tym powinna być mądrzejsza. Jednak naukowcy zauważyli dziwne zjawisko: po przekroczeniu pewnej głębokości (ok. 20 warstw), dokładność sieci zaczynała gwałtownie spadać.

Winowajcą był Vanishing Gradient (Zanikający Gradient). Podczas nauki, informacja o błędach jest przekazywana od końca sieci do jej początku. W bardzo głębokich strukturach, ta informacja "wyparowywała" po drodze, przez co pierwsze warstwy nigdy nie uczyły się niczego konkretnego.

2. Rozwiązanie: Skip Connection (Bloki Rezidualne)

ResNet wprowadził rewolucyjną ideę: pozwólmy sygnałowi płynąć na skróty! Zamiast zmuszać każdą warstwę do ciężkiej pracy nad przekształceniem obrazu, dajemy jej wybór. Jeśli warstwa nie potrafi dodać nic wartościowego, sygnał po prostu ją omija autostradą (Skip Connection).

3. Matematyczna Intuicja

W tradycyjnych sieciach każda warstwa próbuje wyliczyć funkcję H(x). W ResNecie warstwa skupia się tylko na różnicy: F(x) = H(x) - x.

Ostateczny Wynik = F(x) + x
Gdzie x to oryginalna informacja, a F(x) to mała poprawka dodana przez warstwę.

4. Implementacja w Pythonie (PyTorch)

Oto jak wygląda klasyczny blok ResNet (Residual Block) w kodzie. Zwróć uwagę na moment dodawania wejścia identity do wyniku konwolucji.

residual_block.py Python / PyTorch
import torch
import torch.nn as nn

class ResidualBlock(nn.Module):
    def __init__(self, in_channels, out_channels, stride=1):
        super(ResidualBlock, self).__init__()
        
        # Pierwsza warstwa "ciężkiej pracy"
        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, 
                               stride=stride, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.relu = nn.ReLU(inplace=True)
        
        # Druga warstwa "ciężkiej pracy"
        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, 
                               padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(out_channels)

        # Autostrada (Skip Connection)
        self.shortcut = nn.Sequential()
        if stride != 1 or in_channels != out_channels:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(out_channels)
            )

    def forward(self, x):
        identity = x  # Zapamiętujemy wejście

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)

        # KLUCZOWY MOMENT: Dodajemy wejście do przetworzonego sygnału
        out += self.shortcut(identity) 
        out = self.relu(out)
        
        return out

ReLU (Rectified Linear Unit)

Czym jest? To najpopularniejsza funkcja aktywacji w głębokim uczeniu. Działa jak prosty przełącznik: f(x) = max(0, x).

Dlaczego jest kluczowa?

  • Nieliniowość: Pozwala sieci uczyć się złożonych wzorców, a nie tylko prostych linii.
  • Szybkość: Jest niesamowicie tania obliczeniowo (to tylko porównanie z zerem).
  • Brak nasycenia: Dla wartości dodatnich gradient wynosi zawsze 1, co pomaga walczyć z jego zanikaniem.

BatchNorm2d (Batch Normalization)

Czym jest? To technika "normalizacji" danych płynących przez sieć w małych paczkach (batchach).

Dlaczego jest kluczowa?

  • Stabilizacja: Pilnuje, aby wartości nie stały się zbyt wielkie lub zbyt małe, co mogłoby "rozbujać" sieć.
  • Szybsza nauka: Pozwala na stosowanie wyższych współczynników uczenia (Learning Rate), co skraca czas trenowania.
  • Regularyzacja: Działa jak delikatny "filtr ochronny", zapobiegając zbytniemu dopasowaniu do danych treningowych (overfitting).

5. Dlaczego to zmieniło świat?

  • Ekstremalna głębokość: Możliwość trenowania sieci mających 152, 500, a nawet 1000 warstw.
  • Łatwiejsza optymalizacja: Sieci te trenują się szybciej i stabilniej.
  • Uniwersalność: ResNet stał się standardem – niemal każda nowoczesna sieć (w tym Transformery!) używa jakiejś formy połączeń skrótowych.