# Konvoluční neuronové sítě (CNN)

Obrázek `224×224` ve třech barevných kanálech má 150 528 čísel. Napoj ho na plně propojenou vrstvu o tisíci neuronech a máš **150 milionů vah** v jediné vrstvě. Nenatrénuješ to, nevejde se to do paměti a hlavně je to zbytečné - protože detektor svislé hrany je v levém horním rohu užitečný stejně jako v pravém dolním, a plně propojená vrstva se ho musí naučit pro každou pozici zvlášť.

Konvoluční síť tenhle problém řeší jedním nápadem: **naučí se filtr jednou a posouvá ho po celém obrázku.** Z těch 150 milionů vah se stane pár set.

Tahle stránka je o tom, jak se CNN skládá a proč každá vrstva existuje. Předpokládá to [MLP a backpropagation](MLP-a-backpropagation) - trénování je totiž úplně stejné - a [umělý neuron](Neuron-a-perceptron), zejména ReLU.

## Definice a odkud se to vzalo

**Konvoluční síť** je specializovaná dopředná síť pro zpracování dat s **mřížkovou strukturou** - obrazy, zvuk, video.

Inspirace je z biologie a je konkrétní: práce **Hubela a Wiesela z roku 1962** o primární zrakové kůře koček. Zjistili, že jednotlivé neurony reagují na podněty jen v malé části zorného pole (**receptivní pole**) a že různé neurony reagují na různě orientované hrany. Přesně tohle CNN kopíruje.

**Milník: ImageNet 2012.** Alex Krizhevsky se sítí AlexNet snížil chybu klasifikace z **26 % na 15 %**. To odstartovalo nástup hlubokého učení - ne jako nová myšlenka, ale jako důkaz, že to funguje. Konvoluční sítě existovaly od osmdesátých let, chyběla jen data a grafické karty.

## Reprezentace obrazu

Barevný obrázek `32×32` je **trojrozměrná matice `32×32×3`** - kanály R, G, B. Hodnoty pixelů jsou 0-255, případně normalizované na `[0, 1]`.

Ta [normalizace](Metriky-a-vyhodnoceni#základní-typy-dat) není volitelná. Vstupy v rozsahu 0-255 nasytí aktivační funkce a síť se přestane učit hned v první vrstvě.

## Vrstvy CNN

### Konvoluční vrstva

Jádrem je **filtr (kernel)** - malá matice vah, například `5×5×3` - která „klouže" po vstupním tenzoru. V každé pozici se spočítá **skalární součin vah filtru se vstupem** a výsledek se zapíše do **mapy příznaků** (feature map, activation map).

**Receptivní pole** jednoho výstupního bodu odpovídá oblasti filtru na vstupu.

Všimni si hloubky filtru. Filtr `5×5×3` má tu trojku, protože musí pokrýt všechny tři barevné kanály naráz. **Filtr je vždycky tak hluboký jako jeho vstup** a jeho výstup je jedna dvourozměrná mapa.

**Víc filtrů znamená víc map příznaků.** Každý filtr se „učí" detekovat jinou nízkoúrovňovou vlastnost - hrany, barvy, textury. V hlubších vrstvách se z nich skládají složitější reprezentace: části objektů, celé objekty.

**Tohle je nejdůležitější věta na celé stránce: CNN si příznaky navrhne sama.** Vrať se k [příznakovým metodám](Priznakove-metody), kde se LBP a histogramy musely vymyslet ručně. Tady se první vrstva naučí něco, co detektorům hran nápadně připomíná, a nikdo jí to neřekl. Vyplyne to z dat a z toho, že se to hodí pro minimalizaci chyby.

Dvě vlastnosti, které z toho posouvání plynou a stojí za pojmenování:

**Sdílení vah.** Tentýž filtr se používá na všech pozicích, takže se počet parametrů nezávisí na velikosti obrázku. Odtud ta úspora ze 150 milionů na pár set.

**Ekvivariance vůči posunu.** Posuň objekt v obrázku a mapa příznaků se posune stejně. Detektor hrany funguje všude, protože je všude tentýž.

### Aktivace (ReLU)

Po konvoluci následuje prvek-po-prvku aktivace, nejčastěji **ReLU**: `f(x) = max(0, x)`.

**Vnáší do sítě nelinearitu** - bez ní by celá síť byla jedna lineární operace, viz [MLP](MLP-a-backpropagation#co-mlp-je) - **a současně urychluje trénování**, protože potlačuje problém mizejícího gradientu. Derivace ReLU je v kladné části přesně jedna, takže se gradient přes vrstvy neztrácí.

### Pooling

**Redukuje prostorovou velikost map (downsampling).** Nejběžnější je **max-pooling s oknem `2×2` a krokem 2**: zmenší mapu na poloviční rozlišení a ponechá nejsilnější aktivaci v každém okně.

Přínosy jsou dva:

- **úspora paměti a výpočtu** - poloviční rozlišení znamená čtvrtinu bodů,
- **robustnost vůči malým posunům** - když se hrana posune o pixel, maximum v okně `2×2` zůstane stejné.

Ten druhý bod je ta zajímavější polovina. Konvoluce je vůči posunu **ekvivariantní** (výstup se posune), pooling přidává částečnou **invarianci** (výstup se nezmění). Skládáním konvoluce a poolingu tak síť postupně přestává řešit, kde přesně objekt je, a začíná řešit, jestli tam je.

### Plně propojená vrstva (FC)

Poslední vrstvy jsou klasické „dense" vrstvy, které z vektoru vysokoúrovňových příznaků spočítají výsledný **klasifikační vektor**. Na závěr se aplikuje **softmax**, který normalizuje výstupy do pravděpodobnostního rozdělení přes třídy.

**Rozdělení práce v CNN je tedy jasné: konvoluční část dělá extrakci příznaků, plně propojená část dělá klasifikaci.** Tohle je přesně to rozdělení, které u [příznakových metod](Priznakove-metody) dělal člověk a klasifikátor. CNN dělá obojí a učí to naráz.

## Typická architektura LeNet

```
Input → Conv → ReLU → Conv → ReLU → Pool → Conv → ReLU → Pool → FC → Softmax
```

Vzorec, který se opakuje: **konvoluce, aktivace, občas pooling** - a na konci plně propojené vrstvy se softmaxem.

Sleduj, co se v tom sledu děje s rozměry. **Prostorové rozměry klesají** (pooling), zatímco **hloubka roste** (víc filtrů v hlubších vrstvách). Ze `32×32×3` se stane třeba `8×8×64`. Obrázek se mění z „velký a mělký" na „malý a hluboký" - z pixelů na příznaky.

## Trénování CNN

Stejně jako u [MLP](MLP-a-backpropagation): dopředný průchod, výpočet ztráty, zpětný průchod a aktualizace vah.

Ztrátová funkce bývá **křížová entropie**, případně střední kvadratická chyba:

```
Etotal = ½ Σ (tk − yk)²
```

Aktualizace vah gradientním sestupem:

```
w = wi − η · ∂L/∂W
```

Trénink probíhá **v mini-batchích na GPU** a obvykle zabere **desítky až stovky epoch**, kde epocha je jeden průchod celým trénovacím datasetem.

**Backpropagation ve sdílených vahách funguje tak, že se gradienty ze všech pozic sečtou.** Filtr se objevuje na stovkách míst a každé z nich přispěje svým dílem chyby do téže sady vah. Nic dalšího se v algoritmu měnit nemusí - a to je důvod, proč se CNN daly trénovat hned, jak někoho napadly.

## Kde CNN přestávají platit

**Potřebují hodně dat.** AlexNet se trénoval na 1,2 milionu obrázků. Na tisíci obrázcích se CNN od nuly nenatrénuje. Řeší se to **transfer learningem** - vezmeš síť předtrénovanou na ImageNetu, uřízneš poslední vrstvu a dotrénuješ jen ji. V praxi je to výchozí postup a **od nuly se dnes trénuje jen výjimečně**.

**Nejsou invariantní vůči rotaci a měřítku.** Posun ano, otočení ne. Otočený objekt je pro CNN jiný objekt. Řeší se to [augmentací dat](MLP-a-backpropagation#problémy-při-trénování) - do trénovací množiny se přidají otočené a zvětšené varianty.

**Nevidí prostorové vztahy dobře.** Obličej s prohozenýma očima a ústy může síť klidně klasifikovat jako obličej, protože všechny očekávané příznaky jsou přítomné. Pooling tu informaci o poloze zahodil úmyslně a tohle je cena za to.

**Nefungují na tabulková data.** Konvoluce předpokládá, že sousední hodnoty spolu souvisejí. U sloupců v tabulce to neplatí - přeházej sloupce a nic se nezmění. Tam patří [rozhodovací stromy](Priznakove-metody#klasifikační-a-regresní-strom-cart) nebo MLP.

**Nejsou to jediné dnešní řešení.** Od roku 2020 konkurují CNN **Vision Transformery**, které obrázek rozdělí na dlaždice a zpracují je pozorností. Na velkých datech je předčí, na malých ne. Pro většinu praktických úloh je předtrénovaná CNN pořád rozumná a levnější volba.

## Co se na tom nejčastěji rozbije

| Příznak | Kde je problém |
|---|---|
| Síť se neučí vůbec | nenormalizované vstupy 0-255 |
| Trénovací chyba nízká, testovací vysoká | přeučení - augmentace dat, dropout ve FC vrstvách |
| Dojde paměť GPU | příliš velký batch nebo příliš velké mapy - přidej pooling dřív |
| Model funguje na rovných fotkách, na otočených ne | chybí augmentace rotací |
| Síť předpovídá pořád tutéž třídu | příliš velké `η`, nebo silně nevyvážená data |
| Na malém datasetu je výsledek náhodný | trénuješ od nuly - použij transfer learning |
| Rozměry nesedí mezi Conv a FC | zapomenuté zploštění (flatten) map příznaků |

## Co si odnést

**Filtr se naučí jednou a použije všude.** To je celá úspora parametrů.

**Konvoluce dělá extrakci příznaků, FC vrstvy klasifikaci.** CNN se učí obojí naráz.

**Mělké vrstvy najdou hrany, hluboké objekty.** Hierarchie vznikne sama, nikdo ji nepředepisuje.

**Pooling přidává invarianci vůči posunu a šetří paměť.** Zahodí za to informaci o přesné poloze.

**Rozměry jdou z velkých a mělkých na malé a hluboké.**

**Trénování je obyčejný backpropagation**, gradienty sdílených vah se jen sečtou přes pozice.

**Bez hodně dat použij transfer learning.** Od nuly se dnes trénuje výjimečně.

## Kam dál

- **[MLP a backpropagation](MLP-a-backpropagation)** - trénovací algoritmus, který CNN používá beze změny
- **[Příznakové metody](Priznakove-metody)** - co CNN nahradila a proč se to dřív dělalo ručně
- **[Rekurentní sítě a LSTM](Rekurentni-site-a-LSTM)** - druhá specializovaná architektura, tentokrát pro sekvence
- **[Hry a herní strom](Hry-a-herni-strom)** - CNN jako náhrada ohodnocovací funkce v AlphaGo
- **[Nástroje pro UI](Nastroje-pro-UI)** - PyTorch a Keras, ve kterých se to píše
