# Metriky a vyhodnocení modelů

Mám klasifikátor rakoviny s přesností 99 %. Zní to výborně. Nemocný je jeden pacient ze sta, takže model, který napíše „zdravý" úplně všem, má přesnost 99 % taky - a nenajde ani jednoho nemocného.

**Přesnost (accuracy) je nejpoužívanější a nejzavádějící metrika ve strojovém učení.** U nevyvážených dat neříká vůbec nic a přesto se uvádí jako první číslo v každé práci.

Tahle stránka je o tom, čím ji nahradit, jak se čte matice záměn a proč se model nesmí testovat na datech, na kterých se učil. Předpokládá to [klasifikaci a rozpoznávání](Klasifikace-a-rozpoznavani). Nepotřebuješ k tomu žádnou statistiku nad rámec zlomků.

## Základní typy dat

Než se začne měřit, musí se data uvést do stavu, ve kterém se měřit dají.

**Intervalové proměnné** - poloha, váha, výška. Normalizují se do `[0, 1]`:

```
x' = (x − xmin) / (xmax − xmin)
```

**Tohle není kosmetika.** Když má váha rozsah 50-120 a výška 1,5-2,0, každá euklidovská vzdálenost bude určena výhradně vahou a výška se v ní ztratí. Bez normalizace ti [k-NN](Priznakove-metody#k-nejbližších-sousedů-k-nn) i [shlukování](Shlukovani) měří něco jiného, než sis myslel.

**Binární proměnné** - dva stavy, `1` (přítomnost) a `0` (nepřítomnost). Normalizovat se nemusí.

## Metriky vzdálenosti

**Eukleidovská vzdálenost.** Přímá čára, to, co si pod vzdáleností představíš:

```
d(X, Y) = √( Σ (xi − yi)² )
```

**Manhattanská vzdálenost.** Součet absolutních rozdílů, tedy cesta po ulicích pravoúhlého města:

```
d(X, Y) = Σ |xi − yi|
```

Je **odolnější vůči odlehlým hodnotám**, protože nemocní rozdíly na druhou. Jeden příznak, který se liší o deset, přispěje deseti, ne stem.

**Kosinová podobnost.** Úhel mezi vektory:

```
sim(X, Y) = (X · Y) / (‖X‖ · ‖Y‖)
```

Všimni si, že to není vzdálenost, ale **podobnost** - vyšší je lepší, hodnota 1 znamená stejný směr. A hlavně: **ignoruje délku vektorů**. Proto se používá na texty. Dokument o třiceti slovech a dokument o třech tisících se stejným tématem mají skoro stejný směr, ale obrovskou euklidovskou vzdálenost.

**Volba metriky je součást návrhu, ne detail.** Fyzikální veličiny → euklidovská. Data se šumem a odlehlými body → manhattanská. Texty a četnosti → kosinová.

## Přesnost klasifikace

Chybovost a přesnost, nejzákladnější dvojice:

```
ER  = E / ALL              chybovost (error rate)
ACC = OK / ALL = 1 − ER    přesnost (accuracy)
```

U úloh typu **rozpoznávání 1-n** (spojitá řeč, sekvence znaků) to nestačí, protože model může slovo nejen zaměnit, ale i vynechat nebo přidat:

```
ACC = (N − D − S − I) / N
```

kde `N` je počet jednotek, `D` vynechané (deletions), `S` zaměněné (substitutions) a `I` vložené (insertions).

**Ta `I` je důvod, proč tahle metrika může vyjít záporná.** Když model vygeneruje víc jednotek, než jich ve skutečnosti bylo, `I` může být větší než `N`. To není chyba vzorce, to je poctivé měření.

## Matice záměn

Tabulka skutečných proti predikovaným třídám. Pro dvě třídy:

| | Predikce + | Predikce − |
|---|---|---|
| **Skutečnost +** | TP | FN |
| **Skutečnost −** | FP | TN |

- **TP** (true positive) - správně označený pozitiv,
- **FN** (false negative) - **prošvihnutý** pozitiv,
- **FP** (false positive) - falešný poplach,
- **TN** (true negative) - správně označený negativ.

**Nejdůležitější věc na téhle stránce: FN a FP nejsou stejně drahé.** U testu na rakovinu je FN prošvihnutá diagnóza a FP zbytečné vyšetření navíc. U spamového filtru je FP ztracený důležitý e-mail a FN otravná reklama v inboxu. **Která z těch dvou chyb tě víc bolí, rozhoduje o tom, kterou metriku máš sledovat.**

Pozor na orientaci tabulky. Používají se obě konvence a liší se, jestli je řádek skutečnost, nebo odhad:

| Odhad / Reál | 1 | 0 |
|---|---|---|
| **1** | TP | FP |
| **0** | FN | TN |

**Před interpretací si vždycky zkontroluj, co je řádek.** Ve scikit-learn (`ConfusionMatrixDisplay`) je **řádek skutečná třída** a sloupec predikce.

Pro víc tříd je matice `R × R`. Příklad ze tří tříd:

| | a | b | c |
|---|---|---|---|
| **a** | 88 | 4 | 12 |
| **b** | 8 | 65 | 4 |
| **c** | 11 | 15 | 33 |

Na diagonále jsou správné klasifikace, mimo ni záměny. **Z téhle matice se toho dá vyčíst mnohem víc než z jednoho čísla přesnosti.** Třída `c` má jen 33 správných ze 59 a nejčastěji se plete s `b`. Přesnost by ti řekla „78 %" a to, že jedna třída skoro nefunguje, bys nezjistil.

Přesně to je důvod, proč se u [datasetu Digits](Nastroje-pro-UI#příklad-klasifikace-datové-sady-digits) kreslí matice záměn - je z ní vidět, že si model plete osmičku s trojkou, což z přesnosti 96 % nepoznáš.

## Precision, Recall, F-míra

```
Precision = TP / (TP + FP)
Recall    = TP / (TP + FN)
F1        = 2 · Precision · Recall / (Precision + Recall)
```

Slovy, a tohle si zapamatuj v téhle podobě:

**Precision odpovídá na otázku: „Kolik z toho, co jsem označil, bylo správně?"** Jmenovatel je všechno, co model označil za pozitivní.

**Recall odpovídá na otázku: „Kolik z toho, co existovalo, jsem našel?"** Jmenovatel je všechno, co skutečně pozitivní bylo.

**Jdou proti sobě a to je celý smysl toho, že jsou dvě.** Model, který označí za pozitivní úplně všechno, má recall 1,0 a mizernou precision. Model, který označí jediný nejjistější případ, má precision 1,0 a mizerný recall. **Jednu z nich vždycky zvedneš na úkor druhé posunutím prahu rozhodování.**

`F1` je jejich harmonický průměr. Používá se harmonický, ne aritmetický, protože **tvrdě trestá nerovnováhu**. Precision 1,0 a recall 0,0 dá aritmetický průměr 0,5, ale `F1 = 0`. To je správně - takový model je k ničemu.

Vrať se k příkladu z úvodu. Model „všichni zdraví" má accuracy 0,99, recall 0,0 a `F1 = 0`. **Jedna metrika říká výborně, druhá říká úplně nefunguje, a pravdu má ta druhá.**

## Křížová validace

Data se rozdělí na `k` částí, typicky `k = 10`. Model se `k`-krát natrénuje, pokaždé s jinou částí jako testovací a zbytkem jako trénovací. Výsledná přesnost je průměrem.

```mermaid
flowchart LR
    A["data rozdělená na 10 dílů"] --> B["běh 1: test = díl 1"]
    A --> C["běh 2: test = díl 2"]
    A --> D["..."]
    A --> E["běh 10: test = díl 10"]
    B --> F["průměr přesností"]
    C --> F
    D --> F
    E --> F
```

**Odstraňuje závislost na konkrétním rozdělení dat.** Jeden náhodný split ti může dát 96 % nebo 91 % podle toho, jak padly těžké případy - a ty pak měříš náhodu, ne model.

Druhá výhoda: každý vzorek je právě jednou v testovací množině, takže **využiješ všechna data na trénování i na testování**, jen ne naráz. U malých datasetů je to zásadní.

**Kde křížová validace přestává platit:** u časových řad ji nepoužívej. Náhodné rozdělení znamená, že se model učí na budoucnosti a testuje na minulosti, a výsledek bude nesmyslně dobrý. Tam se dělí chronologicky.

Druhý případ: když děláš výběr příznaků nebo ladění parametrů, musí se to dělat **uvnitř** každého běhu. Když vybereš příznaky na celých datech a pak křížově validuješ, testovací data už model ovlivnila a přesnost je nadhodnocená.

## Učební křivka

Závislost chyby na velikosti trénovací množiny, případně na počtu epoch. Kreslí se dvě křivky - trénovací a validační chyba - a z jejich vzájemné polohy se čte diagnóza:

| Co vidíš | Co to znamená | Co s tím |
|---|---|---|
| Obě chyby vysoké, blízko sebe | **podtrénování** (underfitting) | větší model, víc příznaků, delší trénink |
| Trénovací nízká, validační vysoká | **přetrénování** (overfitting) | víc dat, regularizace, dropout, jednodušší model |
| Obě nízké a blízko | model sedí | hotovo |
| Validační klesá a pak roste | přetrénování začalo v tom minimu | early stopping právě tam |

**Tahle tabulka je nejužitečnější věc na celé stránce**, protože převádí obrázek na konkrétní akci. Bez ní se ladí naslepo.

Podrobněji jsou příčiny a protiopatření u [MLP a backpropagation](MLP-a-backpropagation#problémy-při-trénování).

## Praktická pravidla

**Nikdy netestuj na trénovacích datech.** Zní to samozřejmě a stane se to každému, typicky přes příznaky vybrané na celém datasetu.

**U nevyvážených dat neuváděj accuracy.** Uváděj precision, recall a `F1`, nebo rovnou matici záměn.

**Rozhodni předem, jestli tě víc bolí FP, nebo FN.** Podle toho se pak volí práh a metrika, ne obráceně.

**Vždycky se podívej na matici záměn, ne jen na číslo.** Jedno číslo skryje, že jedna třída vůbec nefunguje.

**Normalizuj příznaky před vším, co počítá vzdálenost.** k-NN, k-means, SVM, neuronové sítě. Rozhodovací stromy to nepotřebují.

**Křížovou validaci použij, kdykoliv máš míň než pár tisíc vzorků.** Jeden split tam měří náhodu.

## Co si odnést

**Accuracy u nevyvážených dat nic neříká.** 99 % může znamenat model, který nenajde ani jeden pozitiv.

**Precision = kolik z označených sedělo. Recall = kolik z existujících jsem našel.** Jdou proti sobě.

**F1 je harmonický průměr, aby tvrdě trestal nerovnováhu.**

**Matice záměn řekne víc než jakákoliv jedna metrika.** Podívej se na ni vždycky.

**FN a FP nejsou stejně drahé.** Která chyba bolí víc, je rozhodnutí zadání, ne modelu.

**Křížová validace měří model, jeden split měří náhodu.**

**Normalizace patří před každý výpočet vzdálenosti.**

## Kam dál

- **[Příznakové metody](Priznakove-metody)** - co se vlastně vyhodnocuje
- **[Bayesova klasifikace](Bayesova-klasifikace)** - klasifikátor, který vrací pravděpodobnosti a dá se u něj posouvat práh
- **[MLP a backpropagation](MLP-a-backpropagation)** - přetrénování a jak se proti němu bojuje
- **[Nástroje pro UI](Nastroje-pro-UI)** - `accuracy_score`, `ConfusionMatrixDisplay` a křížová validace ve scikit-learn
