# Vícevrstvý perceptron a backpropagation

Univerzální aproximační teorém říká, že síť s **jednou skrytou vrstvou** dokáže aproximovat libovolnou spojitou funkci s libovolnou přesností. Kdyby to bylo prakticky použitelné, nikdo by hluboké sítě nepotřeboval.

Věta ale neříká, kolik neuronů na to bude potřeba (může jich být exponenciálně mnoho), ani jak ty váhy najít. **Je to důkaz existence, ne návod.** Přesně tenhle rozdíl je důvod, proč se mezi rokem 1969 a 1986 nic nedělo - všichni věděli, že víc vrstev pomůže, a nikdo je neuměl naučit.

Tahle stránka je o algoritmu, který to vyřešil. Předpokládá to [umělý neuron](Neuron-a-perceptron) - zejména aktivační funkce a to, proč musí být diferencovatelné - a je dobré mít přečtenou [lineární regresi](Linearni-regrese), protože ztrátová funkce je tam v jednodušší podobě. Derivace se tu používají, ale nic se nederivuje.

## Co MLP je

Vícevrstvý perceptron obsahuje **jednu nebo víc skrytých vrstev** mezi vstupní a výstupní vrstvou. Nelineární aktivace (sigmoida, tanh, ReLU) ve skrytých neuronech umožňují aproximovat libovolnou spojitou funkci.

Slovo **nelineární** je v té větě to jediné podstatné. Kdyby byly aktivace lineární, složením několika lineárních vrstev vznikne zase lineární funkce a celá síť je jeden neuron s divně spočítanými vahami. **Bez nelinearity je hloubka k ničemu.**

Vrať se k XORu z [předchozí stránky](Neuron-a-perceptron#xor-limit-který-zastavil-obor). Jeden neuron nakreslí jednu přímku. Dva neurony ve skryté vrstvě nakreslí dvě a výstupní neuron je zkombinuje - a dvě přímky už čtverec s úhlopříčnými jedničkami oddělí. **Tohle je celý přínos skryté vrstvy: neskládá vstupy, skládá hranice.**

## Univerzální aproximační teorém

**(Cybenko, 1989.)** Dopředná síť s jednou skrytou vrstvou a dostatečným počtem neuronů se sigmoidální aktivací dokáže s libovolnou přesností aproximovat libovolnou spojitou funkci na kompaktní množině v `Rⁿ`.

Tři věci, které ta věta **neříká** a které se pravidelně přehlížejí:

**Neříká, kolik neuronů.** „Dostatečný počet" může být astronomický. U některých funkcí roste exponenciálně s dimenzí vstupu, zatímco hluboká síť si vystačí s lineárně mnoha.

**Neříká, jak ty váhy najít.** Existence řešení není totéž co jeho nalezení. Chybová funkce je nekonvexní a gradientní sestup do globálního minima nedojde.

**Neříká nic o generalizaci.** Síť, která přesně aproximuje trénovací data, může být na nových datech k ničemu - viz [přeučení](#problémy-při-trénování).

**Proto se dnes staví hluboké sítě, ne široké.** Ne protože by mělké nemohly, ale protože hluboké potřebují míň neuronů a líp se učí.

## Backpropagation

**Rumelhart, Hinton a Williams, 1986.** Algoritmus má dvě fáze a mezi nimi jeden nápad.

### Dopředný průchod

Pro každý vstup `x` se postupně počítají aktivity neuronů vrstva po vrstvě až po výstup `y`. Nic zvláštního - je to prostě spuštění sítě.

### Zpětný průchod

Od výstupní vrstvy směrem ke vstupu se propaguje chyba.

Pro výstupní neuron `i`:

```
Δi = Erri · g'(ini)
```

pro skrytý neuron `j`:

```
Δj = g'(inj) · Σ Wj,i · Δi        (suma přes i)
```

Vlastní úprava vah:

```
Wj,i ← Wj,i + α · aj · Δi
```

**Ta prostřední rovnice je celý algoritmus a stojí za to jí rozumět slovy.** Skrytý neuron neví, jakou má mít správnou hodnotu - nikdo mu ji neřekl. Zjistí ale, jakou chybu způsobil, tak, že si **posbírá chyby neuronů, do kterých posílá svůj výstup, vážené silou toho spojení**. Neuron, který posílá silný signál do neuronu s velkou chybou, nese velkou část viny.

To je ta myšlenka, která chyběla sedmnáct let: **chyba se dá rozdělit mezi skryté neurony podle vah, kterými do výstupu přispěly.**

Ten `g'` v obou rovnicích je důvod, proč **musí být aktivační funkce diferencovatelná**. U sigmoidy je `g' = g(1−g)`, takže se počítá z hodnoty, kterou už máš z dopředného průchodu, a nic navíc to nestojí.

## Ztrátová funkce a gradientní sestup

Typicky se minimalizuje **střední kvadratická chyba**:

```
Etotal = ½ Σ (tk − yk)²        (suma přes výstupy k)
```

To je přesně stejný výraz jako u [nejmenších čtverců](Linearni-regrese#metoda-nejmenších-čtverců). Rozdíl je jediný: u přímky se minimum najde vyřešením soustavy dvou rovnic, tady soustava lineární není a řešení se musí hledat postupně.

Odtud **gradientní sestup**:

```
w_nový = w − η · ∂E/∂w
```

kde `η` je rychlost učení.

Ta jednodušší polovina toho vzorce je znaménko. **Gradient ukazuje směr nejrychlejšího růstu chyby, takže jdeš proti němu.**

`η` je nejdůležitější parametr celého trénování:

- **příliš velké** - přeskočíš minimum a chyba osciluje nebo diverguje,
- **příliš malé** - konverguje, ale trvá to věčnost a snáz uvázneš v mělkém lokálním minimu.

**Tohle je hill climbing na spojité funkci**, se všemi vlastnostmi, které [lokální prohledávání](Lokalni-prohledavani) má. Lokální minima, plošiny i to, že nikdy nevíš, jestli existuje něco lepšího.

## Problémy při trénování

**Lokální minima.** Povrch chybové funkce je obvykle nekonvexní. Zajímavé zjištění z posledních let: **u velkých sítí to skoro nevadí.** Ve vysoké dimenzi je většina stacionárních bodů sedlových, ne lokálních minim, a z těch se dá vyklouznout. Mnohem větší problém jsou rozsáhlé ploché oblasti, kde je gradient skoro nulový.

**Pomalá konvergence.** Řeší se laděním `η`, **momentem** (do kroku se přimíchá část předchozího, což vyhladí oscilace) a **adaptivními optimalizátory** typu Adam, které si rychlost učení upravují pro každou váhu zvlášť. Adam je dnes výchozí volba a je téměř vždycky správná.

**Přeučení (overfitting).** Síť si „zapamatuje" trénovací data, ale selhává na nových. Proti tomu:

- **regularizace** - penalizace velkých vah v chybové funkci,
- **dropout** - během trénování se náhodně vypíná část neuronů, takže se síť nemůže spolehnout na jeden konkrétní,
- **augmentace dat** - umělé rozšíření trénovací množiny (otočení, posunutí, zašumění obrázků),
- **early stopping** - trénink se zastaví, jakmile začne validační chyba růst.

Poznáš to na [učební křivce](Metriky-a-vyhodnoceni#učební-křivka): trénovací chyba klesá, validační roste. **Ta mezera mezi nimi je přesně to, co měříš.**

**Volba topologie.** Počet vrstev a neuronů není jednoznačně dán a neexistuje na to vzorec. Praktický postup: začni malou sítí, zvětšuj ji, dokud se validační chyba zlepšuje, a v okamžiku, kdy se zlepšuje jen trénovací, přestaň.

## Praktická pravidla

**Normalizuj vstupy.** Sigmoida se při velkých vstupech nasytí, derivace spadne k nule a síť se přestane učit. Vstupy do `[0, 1]` nebo `[−1, 1]`, viz [normalizace](Metriky-a-vyhodnoceni#základní-typy-dat).

**Inicializuj váhy malými náhodnými čísly, ne nulami.** Se stejnými vahami dostanou všechny neurony ve vrstvě stejný gradient a zůstanou navždy identické. Náhodnost je tu proto, aby se **symetrie rozbila**.

**Začni s Adamem a `η = 0,001`.** Je to výchozí nastavení skoro všech frameworků a je dobré.

**Sleduj trénovací i validační chybu naráz.** Jedna křivka ti neřekne, jestli se učíš nebo memoruješ.

**Když se nic neděje, zkontroluj nejdřív data, pak `η`, pak topologii.** V tomhle pořadí, protože v tomhle pořadí bývají chyby.

**Přidávej vrstvy dřív než neurony.** Hluboká úzká síť je skoro vždycky lepší než mělká široká se stejným počtem parametrů.

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

| Příznak | Kde je problém |
|---|---|
| Chyba osciluje nebo roste do nekonečna | příliš velké `η` |
| Chyba se skoro nemění | příliš malé `η`, nebo nasycená sigmoida z nenormalizovaných vstupů |
| Všechny neurony ve vrstvě dělají totéž | inicializace nulami - nerozbitá symetrie |
| Trénovací chyba klesá, validační roste | přeučení - dropout, regularizace, víc dat, early stopping |
| Obě chyby vysoké a stejné | podtrénování - větší síť, delší trénink, lepší příznaky |
| Gradient v prvních vrstvách je nulový | mizející gradient - přejdi ze sigmoidy na ReLU |
| Síť funguje na trénování, náhodně na testu | testuješ na jinak předzpracovaných datech než trénuješ |

## Co si odnést

**Skrytá vrstva skládá hranice, ne vstupy.** Proto zvládne XOR.

**Bez nelineární aktivace je hloubka k ničemu** - složení lineárních funkcí je lineární funkce.

**Univerzální aproximační teorém je důkaz existence, ne návod.** Neříká kolik neuronů ani jak je najít.

**Backpropagation rozděluje chybu skrytým neuronům podle vah**, kterými přispěly do výstupu.

**Aktivace musí být diferencovatelná**, jinak `g'` neexistuje a algoritmus nemá co počítat.

**Gradientní sestup je hill climbing se všemi jeho vadami.** Lokální minima, plošiny, žádná záruka.

**`η` je nejdůležitější parametr.** Velké diverguje, malé nedojde.

## Kam dál

- **[Umělý neuron a perceptron](Neuron-a-perceptron)** - stavební kámen, na kterém tohle stojí
- **[Topologie a učení sítí](Topologie-a-uceni-siti)** - jaké druhy sítí ještě existují
- **[Konvoluční sítě](Konvolucni-site)** - MLP přizpůsobené obrázkům
- **[Metriky a vyhodnocení](Metriky-a-vyhodnoceni)** - jak poznat přeučení dřív, než tě potká v produkci
- **[Nástroje pro UI](Nastroje-pro-UI)** - jak se tohle napíše v Kerasu nebo PyTorchi
