markdown
Priznakove-metody.md
markdown
# Příznakové metody rozpoznávání Nejlepší klasifikátor na světě se špatnými příznaky prohraje s k-NN na dobrých. Tohle je věta, kterou ti nikdo neřekne, dokud si ji sám nevyzkoušíš, a přitom rozhoduje o výsledku víc než volba algoritmu. Obrázek číslice `8×8` má 64 pixelů. Můžeš je nasypat rovnou do klasifikátoru a bude to fungovat překvapivě dobře. Můžeš z nich ale spočítat něco chytřejšího - třeba lokální binární vzory - a najednou ti stejný klasifikátor funguje i na fotkách obličejů při různém osvětlení, kde by surové pixely selhaly úplně. Tahle stránka je o tom, čím se objekt popisuje a jak se z popisu vybere to podstatné. Předpokládá to [klasifikaci a rozpoznávání](Klasifikace-a-rozpoznavani), zejména rozhodovací pravidlo `ω = d(x, q)` a diskriminační funkce. Pravděpodobnostní klasifikátory mají vlastní stránku, [Bayesovu klasifikaci](Bayesova-klasifikace). ## Příznakový vektor Obrazy objektů se reprezentují **vektory příznaků `x`** a klasifikace se dělá rozhodovacím pravidlem: ```ω = d(x) resp. ω = d(x, q)``` kde `x` je příznakový vektor a `q` je vektor nastavení klasifikátoru. Co všechno může být příznakem: - **přímo naměřené fyzikální veličiny** - hmotnost, délka, teplota,- **Bag of Words** - četnosti slov, buď přirozené, nebo binární,- **spektrální koeficienty** - typicky z Fourierovy transformace,- **binarizované hodnoty jasů pixelů**,- **histogramy a geometrické charakteristiky** - momenty, plochy, obvody,- **lokální binární vzory (LBP)**. Podívej se na ten seznam ještě jednou. **Jde od syrových dat k počítaným popisům a s každým krokem klesá rozměr a roste invariance.** Surové jasy pixelů se rozsypou, jakmile obrázek posuneš o pixel. Histogram jasů je vůči posunu úplně invariantní - ale zase ztratí veškerou prostorovou informaci. Návrh příznaků je hledání kompromisu mezi těmito dvěma extrémy. ## Lokální binární vzory LBP je krásná ukázka toho, jak se z chytrého nápadu stane robustní příznak. Princip: **popiš lokální texturu obrazu porovnáním jasu středového pixelu s jeho okolím.** Algoritmus: 1. Pro každý pixel vezmi jeho okolí `3×3`.2. Binarizuj sousedy vůči středu: ```s(in, ic) = 1 když in ≥ ic 0 když in < ic``` 3. Seřaď binární hodnoty po směru hodinových ručiček a převeď na dekadické číslo: ```LBP(P,R) = Σ s(in, ic) · 2^n pro n = 0 .. P−1``` **Klíčová vlastnost je v tom porovnání.** LBP nepracuje s absolutními hodnotami jasu, ale jen s tím, který soused je světlejší. Přinásob celý obrázek dvěma - přisvětlíš scénu - a **LBP kód se nezmění o jediný bit**. Tohle je invariance vůči monotónní změně osvětlení a je to důvod, proč LBP funguje na fotkách pořízených v různých podmínkách. Celkový algoritmus rozpoznávání pak vypadá takhle: 1. Rozdělení obrazu na bloky, například `8×8`.2. Výpočet LBP kódu pro každý pixel.3. Agregace: **histogram LBP kódů pro každý blok**.4. Konkatenace histogramů do globálního příznakového vektoru.5. Klasifikace - euklidovská vzdálenost nebo SVM. Kroky 1 a 3 spolu souvisejí a stojí za rozebrání. Histogram sám o sobě zahodí polohu. Rozdělení na bloky ji částečně vrátí - **víš, že tenhle histogram patří levému hornímu rohu**. Dostaneš tak popis, který je odolný vůči malým posunům uvnitř bloku, ale rozliší oko od úst. ## Výběr příznaků Motivace je trojí: **cena měření**, **cena výpočtu** a to hlavní - **nevhodné příznaky mohou snížit přesnost**. Ten třetí důvod je neintuitivní. Zdálo by se, že víc informace nemůže uškodit. Uškodí: příznak, který s třídou nesouvisí, přidává šum, a klasifikátor se na něm může přeučit. U [k-NN](#k-nejbližších-sousedů-k-nn) navíc každý nadbytečný rozměr ředí vzdálenosti a všechny body se stanou stejně vzdálené. ### Náhodný výběr Postupné přidávání nebo ubírání příznaků a ověření klasifikátorem. Hrubá síla, ale funguje a je to jediná metoda, která **měří to, co doopravdy chceš** - přesnost výsledného klasifikátoru. ### Dokumentová frekvence Pro textové úlohy. Term frequency: ```TF(i,j) = n(i,j) / Σk n(k,j)``` kolikrát se termín `i` vyskytl v dokumentu `j`, normalizováno délkou dokumentu. ### TF-IDF Samotné TF má vadu: slovo „a" má vysokou frekvenci ve všech dokumentech a nerozliší nic. IDF ho potlačí: ```TF-IDF = TF · IDF, IDF(i) = log( |D| / |{j : ti ∈ dj}| )``` `|D|` je počet všech dokumentů, jmenovatel počet těch, ve kterých se termín vyskytl. **Slovo, které je ve všech dokumentech, má IDF rovné `log(1) = 0` a vypadne úplně.** Slovo, které je jen v pár dokumentech, dostane vysokou váhu. To je celá myšlenka TF-IDF: **důležité je to, co je časté tady a vzácné jinde.** ### Vzájemná informace Obecná míra závislosti mezi příznakem a třídou: ```MI(X; Y) = Σ Σ p(x, y) · log( p(x, y) / (p(x)·p(y)) ) y∈Y x∈X``` Když jsou `X` a `Y` nezávislé, platí `p(x,y) = p(x)·p(y)`, logaritmus je nula a `MI = 0`. **Vzájemná informace je tedy míra toho, o kolik se liší skutečnost od nezávislosti** - přesně to, co chceš u výběru příznaků vědět. Výhoda MI proti korelaci: zachytí i nelineární závislost. Nevýhoda: potřebuje odhad sdružené pravděpodobnosti, což u spojitých příznaků znamená diskretizaci a s ní další rozhodnutí. ## k-nejbližších sousedů (k-NN) Nejjednodušší použitelný klasifikátor, jaký existuje. Nemá žádné trénování - **trénovací data jsou model**. - **1-NN** - třída je určena podle nejbližšího souseda.- **k-NN** - vezme se `k` nejbližších a rozhodne většina.- Používají se různé [metriky vzdálenosti](Metriky-a-vyhodnoceni#metriky-vzdálenosti). Hranice mezi třídami je **lokální** - nedělí prostor jednou nadrovinou, ale skládá se z kousků kolem jednotlivých bodů. Proto k-NN zvládne libovolně zprohýbanou hranici, kterou by [perceptron](Neuron-a-perceptron) nikdy nenašel. **Volba `k` je kompromis.** Malé `k` (třeba 1) se přizpůsobí každému bodu včetně šumu a přeučí se. Velké `k` hranici vyhladí, ale rozmaže drobné třídy. Praktické pravidlo je zkusit několik hodnot [křížovou validací](Metriky-a-vyhodnoceni#křížová-validace) a **volit `k` liché**, aby u dvou tříd nevznikla remíza. **Kde k-NN přestává platit:** je pomalý při klasifikaci (musí spočítat vzdálenost ke všem trénovacím bodům), potřebuje mít celou trénovací množinu v paměti a **rozpadá se ve vysokých dimenzích**, kde jsou si všechny body zhruba stejně vzdálené. Na obrázcích `8×8` funguje výborně, na tisícirozměrných vektorech přestává. ## Klasifikátor na principu minimální vzdálenosti Ještě jednodušší než k-NN. Každou třídu reprezentuje **jeden vzorový obraz (etalon)** `es`, `s = 1, ..., R`, a klasifikuje se podle vzdálenosti k němu: ```ωr = ‖er − x‖ = min ‖es − x‖ s=1..R``` Ve scikit-learn se tomu říká `NearestCentroid` a etalonem je průměr trénovacích vektorů dané třídy. **Porovnání s k-NN je poučné.** Minimální vzdálenost drží `R` bodů (jeden na třídu), k-NN drží všechny. Minimální vzdálenost je proto řádově rychlejší a řádově hloupější - dělí prostor lineárně a **na třídu, která má dvě oddělená ohniska, selže úplně**, protože její průměr padne někam mezi ně. Přesně to se stane na datasetu Digits: `NearestCentroid` dá kolem 90 %, `KNeighborsClassifier(n_neighbors=3)` kolem 98 %. Rozdíl je vidět v [matici záměn](Metriky-a-vyhodnoceni#matice-záměn) - osmičky a trojky, které se píšou různě, padají na centroid. ## Klasifikační a regresní strom (CART) Popis vztahů pomocí stromu: **uzly jsou rozhodovací pravidla, listy přiřazení ke třídě**. - **Princip:** postupné dělení prostoru příznaků na menší, homogennější podoblasti.- **Rozhodování:** procházení od kořene k listu na základě testování `xj ≤ τ`.- **Dělení:** binární nebo ternární.- **Výhoda:** vysoká interpretovatelnost, tedy *white-box* model. Ta interpretovatelnost je hlavní důvod, proč se stromy pořád používají, přestože samotný strom bývá slabší než [neuronová síť](MLP-a-backpropagation). **Můžeš vytisknout cestu od kořene k listu a máš vysvětlení rozhodnutí ve tvaru, kterému rozumí i člověk, který o strojovém učení nikdy neslyšel** - „zůstatek pod 20 000 a nezaměstnaný, tedy zamítnuto". U banky nebo v medicíně to není luxus, ale požadavek. **Kde stromy přestávají platit:** jeden strom se snadno přeučí a je nestabilní - změna pár trénovacích bodů může přeskládat celý strom. Řeší se to spojením mnoha stromů do **náhodného lesa**, který je přesnější a o tu interpretovatelnost zase přijde. ## Kterou metodu kdy | Situace | Metoda ||---|---|| Málo dat, nízká dimenze, nechceš trénovat | k-NN || Potřebuješ rychlost a třídy jsou kompaktní | minimální vzdálenost || Potřebuješ vysvětlit rozhodnutí | rozhodovací strom || Hodně příznaků, textová data | [naivní Bayes](Bayesova-klasifikace) || Hodně dat, obrázky | [neuronová síť](Konvolucni-site) || Neznáš třídy | [shlukování](Shlukovani) | ## Co se na tom nejčastěji rozbije | Příznak | Kde je problém ||---|---|| Vysoká přesnost na trénovacích datech, nízká na testovacích | přeučení - u k-NN příliš malé `k`, u stromu chybí prořezání || Jeden příznak převálcuje všechny ostatní | chybí normalizace - viz [intervalové proměnné](Metriky-a-vyhodnoceni#základní-typy-dat) || Přidání příznaků zhoršilo výsledek | šumové příznaky, potřebuje výběr příznaků || Klasifikátor je ve vysoké dimenzi náhodný | prokletí dimenzionality, k-NN tam nefunguje || LBP nefunguje na hladkých plochách | LBP popisuje texturu, na plochách bez struktury nemá co měřit || Minimální vzdálenost plete dvě třídy | třída má víc ohnisek a centroid padl mezi ně | ## Co si odnést **Příznaky rozhodují víc než klasifikátor.** Dobré příznaky zachrání hloupou metodu, obráceně to neplatí. **LBP je invariantní vůči osvětlení**, protože porovnává, ne měří. **TF-IDF vyváží časté a vzácné.** Slovo ve všech dokumentech má váhu nula. **Vzájemná informace měří odchylku od nezávislosti** a zachytí i nelineární vztah. **k-NN nemá trénování, ale platí za to při klasifikaci** a ve vysoké dimenzi se rozpadá. **Strom je jediná metoda, která umí vysvětlit rozhodnutí větou.** ## Kam dál - **[Bayesova klasifikace](Bayesova-klasifikace)** - pravděpodobnostní přístup k témuž- **[Metriky a vyhodnocení](Metriky-a-vyhodnoceni)** - jak se pozná, který klasifikátor je lepší- **[Shlukování](Shlukovani)** - co dělat, když nemáš označená data- **[Konvoluční sítě](Konvolucni-site)** - metoda, která si příznaky navrhne sama- **[Nástroje pro UI](Nastroje-pro-UI)** - jak se tohle všechno napíše ve scikit-learn