Shlukování a snížení dimenze: k-means, PCA a t-SNE
k-means krok za krokem, lokální optima a k-means++, volba počtu shluků loktem a siluetou, DBSCAN na nekonvexních shlucích, prokletí dimenze, analýza hlavních komponent a mapa t-SNE ručně psaných číslic.
Série Základy AI Díl 45 z 83
- Mapa umělé inteligence: co je co a jak to do sebe zapadá
- Stručná historie umělé inteligence: od Turinga po jazykové modely
- Data, model, trénink, inference: základní pojmy na jednom příkladu
- Jak číst matematický zápis: symboly, indexy, sumy a kvantifikátory
- Množiny a relace: stavebnice, ze které se skládají definice v AI
- Funkce a zobrazení: proč je každý model v AI funkce
- Logika a důkazy: pravidla, podle kterých se v AI uvažuje
- Grafy a stromy: struktura, na které stojí hledání i neuronové sítě
- Lineární algebra pro strojové učení: vektory, matice a proč AI hlavně násobí
- Derivace, gradient a řetízkové pravidlo: jak model zjistí, kterým směrem se učit
- Gradientní sestup: jak se model učí
- Co je pravděpodobnost: od hodu kostkou ke Kolmogorovovým axiomům
- Podmíněná pravděpodobnost a Bayesova věta: jak změnit odhad, když se dozvíte něco nového
- Náhodná veličina a distribuční funkce: jedna funkce, která o rozdělení řekne všechno
- Funkce hustoty a pravděpodobnostní funkce: proč má spojitá veličina v bodě pravděpodobnost nula
- Střední hodnota, rozptyl a kovariance: kde rozdělení leží, jak je široké a co s čím souvisí
- Přehled pravděpodobnostních rozdělení: Bernoulli, binomické, Poisson, rovnoměrné, normální a exponenciální
- Zákon velkých čísel a centrální limitní věta: proč se průměry chovají tak předvídatelně
- Statistika a odhady parametrů: maximální věrohodnost, MAP a intervaly spolehlivosti
- Teorie informace: entropie, křížová entropie a KL divergence — odkud se berou ztrátové funkce
- Prohledávání stavového prostoru: BFS, DFS, UCS a A* s animacemi
- Hry a protivník: minimax, alfa-beta ořezávání a Monte Carlo tree search
- Splňování omezujících podmínek: backtracking, propagace omezení a AC-3 na sudoku a mapě krajů
- Logika a znalostní systémy: dopředné a zpětné řetězení, rezoluce a expertní systémy
- Plánování: STRIPS, svět kostek, heuristiky z relaxace a plánování v AI agentech
- Lokální hledání a simulované žíhání: obchodní cestující přes krajská města
- Genetické algoritmy: populace, křížení, mutace a výběr na batohu na výlet
- Evoluční strategie a genetické programování: od pravidla jedné pětiny po Keplerův zákon
- Optimalizace mravenčí kolonií: jak feromonová stopa najde krátkou cestu
- Optimalizace hejnem částic: setrvačnost, vlastní zkušenost a zkušenost hejna
- Neuroevoluce: evoluce vah i tvaru neuronových sítí a algoritmus NEAT
- Fuzzy množiny a funkce příslušnosti: jak zapsat „trochu teplo“
- Fuzzy logika a pravděpodobnost: proč „trochu teplo“ neznamená „pravděpodobně teplo“
- Fuzzy logika: t-normy, implikace a pravidla KDYŽ–PAK
- Fuzzy řízení: Mamdani a Sugeno od ventilátoru po kyvadlo na vozíku
- Fuzzy shlukování: algoritmus fuzzy c-means a body mezi shluky
- Neuro-fuzzy systémy (ANFIS): fuzzy pravidla, která se učí z dat
- Markovovy řetězce: přechodová matice, stacionární rozdělení a PageRank
- Skryté Markovovy modely: Viterbiho algoritmus a nepoctivé kasino
- Bayesovské sítě: proč je tráva mokrá a co z toho plyne pro postřikovač
- Kalmanův filtr: jak z nepřesných měření odhadnout, kde auto je a jak rychle jede
- Druhy strojového učení: s učitelem, bez učitele, s částečným učitelem a další
- Přeučení a regularizace: proč model, který zná data nazpaměť, selže
- Vyhodnocení modelu: křížová validace, F1 a křivka ROC
- Shlukování a snížení dimenze: k-means, PCA a t-SNE
- Klasifikace a regrese: dvě úlohy učení s učitelem
- Lineární regrese: nejmenší čtverce geometricky i maticově
- Polynomiální a nelineární regrese: jak přímku ohnout
- Logistická regrese: sigmoida, šance a křížová entropie
- Vícetřídní klasifikace a softmax: od dvou tříd k mnoha
- Naivní Bayesův klasifikátor: spamový filtr, který funguje lépe, než by měl
- Ztrátové funkce: co přesně model minimalizuje
- Rozhodovací stromy a k nejbližších sousedů: modely bez vzorců
- Ansámbly: náhodný les a gradient boosting
- SVM a jádrový trik: nejširší hranice a jak ji ohnout
- Signál a vzorkování: proč platí Nyquistův teorém
- Fourierova transformace: rozklad signálu na frekvence
- Filtry a konvoluce: vyhlazení, hrany a odstranění šumu
- Zvuk a řeč: spektrogram, melová škála a MFCC
- Obraz jako signál: pixely, barvy, konvoluce a hrany
- Perceptron a umělý neuron: nejjednodušší neuronová síť a co neumí
- Neuronová síť od nuly: zpětné šíření chyby krok za krokem
- Aktivace, inicializace a normalizace: drobnosti, na kterých hluboká síť stojí
- Konvoluční sítě: jak síť poznává obrázky
- Rekurentní sítě: paměť pro posloupnosti a mizející gradient
- LSTM a GRU: brány, které rozhodují, co si síť zapamatuje
- Autoenkodéry: síť, která se učí data stlačit a zase rozbalit
- Embeddingy a word2vec: jak se slovo stane vektorem
- Mechanismus pozornosti: jak se model naučí, kam se dívat
- Transformery a velké jazykové modely: architektura krok za krokem
- Tokenizace: jak se text rozseká na kousky pro model
- Předtrénování a škálování: proč větší model a víc dat funguje
- Doladění a RLHF: jak se z doplňovače textu stane asistent
- Prompty, kontext a RAG: jak modelu dát správné informace
- Variační autoenkodéry (VAE): nové obrázky ze spojitého latentního prostoru
- Generativní adversariální sítě (GAN): padělatel proti detektivovi
- Difúzní modely: jak se z čistého šumu stane obrázek
- Markovovy rozhodovací procesy: stavy, akce, odměny a Bellmanovy rovnice
- Q-learning a DQN: učení hodnoty akcí od tabulky po neuronovou síť
- Policy gradient a PPO: učení přímo strategie
- Jak funguje AI agent: jazykový model ve smyčce s nástroji
- Programování s AI agenty: zadání, testy a kontrola
- Vyhodnocení a bezpečnost AI systémů: jak měřit a jak hlídat
Celá osnova série 83 z 83 témat hotovo
- Jak k-means hledá shluky, proč záleží na startu a jak zvolit jejich počet.
- Proč ve vysokých dimenzích přestávají fungovat vzdálenosti.
- Co dělá PCA a co t-SNE a proč mapě t-SNE nevěřit všechno.
Co se hodí znát předem: Druhy strojového učení: s učitelem, bez učitele, s částečným učitelem a další, Lineární algebra pro strojové učení: vektory, matice a proč AI hlavně násobí
Obchod má milion zákazníků a o každém ví, co kupuje, kdy a za kolik. Nikdo mu ale neřekl, jaké „typy“ zákazníků existují — to chce zjistit. Genetik má tisíce buněk a u každé změřenou aktivitu dvaceti tisíc genů a chce vědět, kolik druhů buněk v tkáni je. V obou případech chybí správné odpovědi, ze kterých by se dalo učit. Tohle je učení bez učitele: hledáme strukturu v datech samotných. Dvě jeho nejčastější podoby jsou shlukování (rozdělit data do skupin) a snížení dimenze (zobrazit data s tisíci čísly tak, aby je člověk uviděl).
Navazuje na díly Druhy strojového učení, kde se k-means objevil poprvé, a Lineární algebra. Měkkou variantu shlukování, kde bod může patřit do více skupin napůl, probírá díl Fuzzy shlukování.
1. k-means krok za krokem
Definice — úloha k-means a Lloydův algoritmus
Nechť d ≥ 1 a n ≥ 1 jsou přirozená čísla, x1, …, xn ∈ ℝd body a k ∈ ℕ, 1 ≤ k ≤ n, počet shluků. Přiřazení je zobrazení c : {1, …, n} → {1, …, k}, které bodu xi přiřadí číslo jeho shluku. Pro středy μ1, …, μk ∈ ℝd a přiřazení c je inercie
J(μ1, …, μk, c) = ∑i=1n ‖xi − μc(i)‖2,
kde ‖x − y‖ = √∑r=1d (xr − yr)2 je euklidovská vzdálenost bodů x, y ∈ ℝd. Úloha k-means je najít středy a přiřazení, pro které je J nejmenší možné. (Díl Fuzzy shlukování zapisuje tutéž úlohu s počtem shluků c, středy vj a přiřazením „shluk“; tady držíme písmeno k z názvu metody.)
Lloydův algoritmus (přibližné řešení úlohy k-means). Vstup: body x1, …, xn ∈ ℝd a počet shluků k. Výstup: středy μ1, …, μk a přiřazení c. Kroky:
- Za počáteční středy zvol k navzájem různých bodů z x1, …, xn (náhodně).
- Přiřazení: pro každé i = 1, …, n zvol c(i) ∈ argminj ∈ {1, …, k} ‖xi − μj‖2; je-li nejbližších středů víc a je mezi nimi dosavadní střed bodu, ponech bod v jeho shluku.
- Zastavení: pokud se přiřazení oproti předchozímu průchodu nezměnilo, skonči a vrať středy a přiřazení.
- Středy: pro každé j = 1, …, k označ Sj = {i : c(i) = j} a je-li Sj ≠ ∅, polož μj = 1/|Sj| ∑i ∈ Sj xi (průměr bodů shluku; prázdný shluk střed nemění).
- Pokračuj krokem 2.
Algoritmus tedy střídá dva kroky — každý bod přiřadí nejbližšímu středu a každý střed přesune do průměru svých bodů —, dokud se přiřazení mění.
Na hřiště postavíme k vlajek. Každé dítě se postaví k nejbližší vlajce. Pak každou vlajku přeneseme doprostřed hloučku, který se u ní sešel. Děti se znovu rozhlédnou, některé přeběhnou k vlajce, která je teď blíž — a tak dál, dokud se nikdo nepohne. Ani jeden krok nemůže inercii zvýšit, takže algoritmus se vždy zastaví.
J = ∑i=1n ‖xi − μc(i)‖2
- J
- inercie — jedno číslo, kterým se dá porovnat kterékoli rozdělení bodů s kterýmkoli jiným; algoritmus ho snižuje
- ∑i=1n
- součet přes všechny body — každý bod musí někam patřit a každý svým „nepohodlím“ přispěje
- μc(i)
- střed shluku, do kterého je bod i přiřazený (c(i) ∈ {1, …, k}) — bod se porovnává jen se svým středem, ne se všemi; proto má smysl krok, který body přeřazuje
- ‖ · ‖2
- čtverec euklidovské vzdálenosti — dvakrát vzdálenější bod stojí čtyřikrát víc, takže vzdálené body se trestají přednostně; a právě pro čtverec je nejlepším středem obyčejný průměr (viz větu níže)
Oba kroky Lloydova algoritmu jako pseudokód (Sj je množina bodů přiřazených ke středu j):
vstup: body x₁ … xₙ, počet shluků k
μ₁ … μₖ ← k různých náhodně vybraných bodů
opakuj:
pro každý bod i: # krok přiřazení
c(i) ← argmin_j ‖xᵢ − μⱼ‖²
když se žádné c(i) nezměnilo: vrať μ, c
pro každý shluk j: # krok středů
Sⱼ ← { i : c(i) = j }
μⱼ ← (1/|Sⱼ|) · ∑_{i ∈ Sⱼ} xᵢ
# (prázdný shluk: střed nech, kde je)
Věta — žádný krok inercii nezvýší
Nechť x1, …, xn ∈ ℝd, 1 ≤ k ≤ n a Lloydův algoritmus běží podle definice výše (včetně pravidla, že při shodné vzdálenosti zůstane bod ve svém shluku). Pak
- žádný krok přiřazení ani krok středů nezvětší inercii J;
- algoritmus skončí po konečně mnoha průchodech.
Důkaz. Krok přiřazení: člen ‖xi − μc(i)‖2 se nahradí nejmenším ze všech ‖xi − μj‖2, takže se nezvětší.
Krok středů: pro neprázdnou množinu indexů S jednoho shluku s průměrem x̄ = 1/|S| ∑i∈S xi a libovolné μ ∈ ℝd platí
∑i∈S ‖xi − μ‖2 = ∑i∈S ‖xi − x̄‖2 + |S| · ‖x̄ − μ‖2
(smíšený člen 2 ∑ (xi − x̄) · (x̄ − μ) je nulový, protože ∑ (xi − x̄) = 0). Druhý sčítanec je ≥ 0 a nulový právě pro μ = x̄, takže průměr je nejlepší možný střed. Prázdný shluk do J nepřispívá a jeho střed se nemění.
Přiřazení c : {1, …, n} → {1, …, k} je konečně mnoho (kn) a při každé změně přiřazení inercie ostře klesne (při shodné vzdálenosti bod zůstává ve svém shluku), takže se žádné nezopakuje a algoritmus skončí. ∎ Věta neříká, že konec je globální minimum — jen že algoritmus nebude cyklit. Podrobnější verzi s fuzzy příslušnostmi má díl Fuzzy shlukování.
Data: pět skupin po čtyřiceti bodech v rovině. Algoritmus to neví — dostane jen 200 dvojic čísel a k = 5. Středy na začátku vybere náhodně mezi body.
Inercie po jednotlivých krocích: 1191,6 → 521,9 → 448,2 → … → 407,1 → 335,1 → 166,3 → 124,8. Nejdřív rychle klesne, pak se osm kroků skoro nic neděje — jeden střed se pomalu „prodírá“ mezi dvěma skupinami — a nakonec se během tří kroků všechno srovná. Po dvanácti krocích algoritmus našel všech pět skupin.
Příklad — k-means ručně na šesti číslech
Body na přímce 1, 2, 4, 7, 9, 10, k = 2, start μ1 = 1, μ2 = 2 (záměrně špatný — oba středy vlevo). Řádek tabulky = středy, přiřazení k nim a inercie (barvy podle vzorce výše: středy, sčítance ‖xi − μc(i)‖2 a výsledné J):
| krok | μ1; μ2 | shluk 1 | shluk 2 | inercie J |
|---|---|---|---|---|
| 0 | 1; 2 | 1 | 2, 4, 7, 9, 10 | 0 + 0 + 22 + 52 + 72 + 82 = 142 |
| 1 | 1; 6,4 | 1, 2 | 4, 7, 9, 10 | 0 + 1 + 2,42 + 0,62 + 2,62 + 3,62 = 26,84 |
| 2 | 1,5; 7,5 | 1, 2, 4 | 7, 9, 10 | 0,25 + 0,25 + 6,25 + 0,25 + 2,25 + 6,25 = 15,5 |
| 3 | 7/3; 26/3 | 1, 2, 4 | 7, 9, 10 | 42/9 + 42/9 ≈ 9,33 |
Středy jsou průměry předchozího řádku: 2 + 4 + 7 + 9 + 10/5 = 6,4; pak 1 + 2/2 = 1,5 a 4 + 7 + 9 + 10/4 = 7,5; nakonec 1 + 2 + 4/3 = 7/3 ≈ 2,33 a 7 + 9 + 10/3 = 26/3 ≈ 8,67. Ve 3. kroku je součet čtverců v každém shluku 42/9. Bod 4 přeběhl ve 2. kroku, protože |4 − 1,5| = 2,5 < |4 − 7,5| = 3,5. Ve 3. kroku se přiřazení nezměnilo — konec. Inercie klesala 142 → 26,84 → 15,5 → 9,33, jak věta slibuje.
2. Lokální optima a k-means++
Ne každý start dopadne dobře. Lloydův algoritmus jen zlepšuje to, co má; když na začátku padnou dva středy do jedné skupiny a žádný do jiné, zůstane v lokálním optimu:
Vpravo se pravá horní skupina rozdělila na dvě a skupiny vlevo nahoře a uprostřed dostaly společný střed. Žádný bod už nechce přeběhnout, takže algoritmus skončil — s inercií 2,6× horší.
Definice — k-means++
Nechť x1, …, xn ∈ ℝd jsou body, mezi kterými je aspoň k navzájem různých, a k ∈ ℕ, 1 ≤ k ≤ n. Jsou-li už vybrány středy μ1, …, μj−1, označme pro bod x ∈ ℝd
D(x) = minl ∈ {1, …, j−1} ‖x − μl‖
jeho vzdálenost k nejbližšímu už vybranému středu. k-means++ (Arthur a Vassilvitskii, 2007) je tento způsob volby počátečních středů. Vstup: body x1, …, xn a k. Výstup: středy μ1, …, μk. Kroky:
- μ1 = xi, kde index i ∈ {1, …, n} je vybrán náhodně, každý s pravděpodobností 1/n.
- Pro j = 2, …, k: μj = xi, kde index i je vybrán náhodně s pravděpodobností P(xi) = D(xi)2/∑l=1n D(xl)2 (jmenovatel je kladný, protože dokud je vybráno méně než k středů, leží aspoň jeden z různých bodů mimo ně).
- Středy μ1, …, μk použij místo kroku 1 Lloydova algoritmu a pak ho spusť obvyklým způsobem.
Každý další střed se tedy volí náhodně, ale body daleko od všech dosavadních středů mají větší šanci.
Vlajky se nezapichují kamkoli: každou další je nejpravděpodobnější postavit tam, kde je od ostatních vlajek daleko. Dvě vlajky v jedné skupině jsou tak nepravděpodobné. Pořád je to ale náhoda, proto se k-means v praxi pouští několikrát a bere se výsledek s nejmenší inercií.
P(x) = D(x)2/∑x′ D(x′)2
- P(x)
- pravděpodobnost, že se dalším středem stane bod x
- D(x)2
- čtverec vzdálenosti k nejbližšímu už vybranému středu — bod daleko od všech středů je nejspíš ve skupině, která střed ještě nemá; už vybraný bod má D = 0, takže nemůže být vybrán znovu. Čtverec je tu ze stejného důvodu jako v inercii: bod přispívá k inercii právě D(x)2, a Arthur a Vassilvitskii (2007) díky tomu dokázali, že očekávaná inercie po samotném startu je nejvýš 8(ln k + 2)-krát větší než optimum
- ∑x′ D(x′)2
- součet přes všechny body — dělí se jím jen proto, aby se pravděpodobnosti sečetly na 1
Příklad — druhý střed k-means++ pro body 1, 2, 4, 7, 9, 10
Ať první střed padl na bod 1. Pak D(x)2 pro ostatní body je 1, 9, 36, 64, 81 a součet 191 (barvy podle vzorce výše). Bod 10 bude druhým středem s pravděpodobností P(10) = 81/191 = 42,4 %, bod 2 jen s P(2) = 1/191 = 0,5 %. Že druhý střed padne do pravé skupiny {7, 9, 10}, má pravděpodobnost 36 + 64 + 81/191 = 94,8 %. Náhodný start (každý ze zbylých pěti bodů se stejnou šancí) by tam trefil jen 3/5 = 60 %.
| 100 běhů, k = 5 | náhodný start | k-means++ |
|---|---|---|
| našlo nejlepší řešení (inercie 124,8) | 56 % | 88 % |
| průměrná inercie | 233,0 | 151,7 |
| nejhorší inercie | 578,6 | 436,0 |
| průměrně kroků | 5,5 | 2,8 |
Chytrý start pomáhá dvakrát: častěji vede k dobrému řešení a algoritmus pak potřebuje polovinu kroků, protože středy začínají skoro na svém místě. Když pustíme k-means++ desetkrát a vezmeme nejlepší běh, je šance, že všech deset selže, při 12 % neúspěchů na běh menší než jedna ku miliardě — pokud jsou běhy nezávislé (pravděpodobnosti se pak násobí: 0,1210 ≈ 6,2 · 10−10).
3. Kolik shluků?
Zatím jsme k = 5 prozradili. Ve skutečnosti ho neznáme — a inercii k jeho volbě použít nemůžeme přímo: s víc středy klesá vždycky, až na nulu pro k = n, kdy má každý bod svůj střed.
Definice — metoda lokte a silueta
Metoda lokte. Nechť pro každé k = 1, 2, …, kmax je J*(k) nejmenší inercie, kterou jsme pro k shluků našli (třeba nejlepší z několika běhů k-means++). Metoda lokte vynese body (k, J*(k)) do grafu a zvolí to k, za kterým se pokles J*(k) − J*(k + 1) výrazně zmenší (graf tam má „loket“). Je to vizuální pravidlo, ne přesné kritérium — co je „výrazně“, matematicky určeno není.
Silueta. Nechť x1, …, xn ∈ ℝd jsou navzájem různé body, k ≥ 2 a C1, …, Ck ⊆ {1, …, n} neprázdné, navzájem disjunktní množiny indexů s C1 ∪ … ∪ Ck = {1, …, n} (shluky). Pro bod i ∈ Cj definujeme:
- soudržnost (pro |Cj| ≥ 2) a(i) = 1/|Cj| − 1 ∑l ∈ Cj, l ≠ i ‖xi − xl‖, průměrnou vzdálenost k ostatním bodům vlastního shluku;
- oddělení b(i) = minh ≠ j 1/|Ch| ∑l ∈ Ch ‖xi − xl‖, průměrnou vzdálenost k bodům nejbližšího cizího shluku;
- siluetu s(i) = b(i) − a(i)/max(a(i), b(i)) pro |Cj| ≥ 2, s(i) = 0 pro |Cj| = 1 (jmenovatel je kladný, protože body jsou různé, a tedy b(i) > 0);
- průměrnou siluetu rozkladu s̄ = 1/n ∑i=1n s(i).
Vždy −1 ≤ s(i) ≤ 1. Silueta bodu je tedy kladná, právě když má bod k vlastnímu shluku v průměru blíž než k nejbližšímu cizímu. Ze všech zkoušených k se volí to s největší průměrnou siluetou s̄.
Silueta se ptá každého bodu: „Jsi blíž svým, nebo sousedům?“ Bod hluboko ve svém shluku má siluetu blízko 1, bod na hranici kolem 0 a bod ve špatném shluku záporné číslo. Když rozdělíme jednu skupinu na dvě, body na nové hranici mají najednou souseda hned vedle — a silueta klesne.
s(i) = b(i) − a(i)/max(a(i), b(i))
- s(i)
- silueta bodu i; průměr přes všechny body hodnotí celé rozdělení
- a(i)
- průměrná vzdálenost k ostatním bodům vlastního shluku — soudržnost; odčítá se, protože čím je menší, tím líp bod do shluku zapadá
- b(i)
- průměrná vzdálenost k bodům nejbližšího cizího shluku — oddělení; bere se nejbližší cizí shluk, protože kdyby bod patřil jinam, tak nejspíš tam
- max(a, b)
- dělení stáhne výsledek do intervalu [−1, 1] a udělá ho nezávislým na měřítku — když všechny souřadnice zdvojnásobíme, silueta se nezmění
Příklad — silueta pro shluky {1, 2, 4} a {7, 9, 10}
Bod 4 (barvy podle vzorce výše): a = |4 − 1| + |4 − 2|/2 = 2,5; b = 3 + 5 + 6/3 ≈ 4,67; s = 4,67 − 2,5/4,67 ≈ 0,46. Leží na kraji svého shluku, a tak má siluetu nejmenší ze všech šesti bodů.
Bod 1: a = 1 + 3/2 = 2; b = 6 + 8 + 9/3 ≈ 7,67; s = 7,67 − 2/7,67 ≈ 0,74. Průměrná silueta všech šesti bodů vyjde 0,66.
Inercie spadne z 330,2 pro k = 4 na 124,8 pro k = 5 a pak už klesá jen o desítky (110,9; 96,8; 88,4…) — loket je u pětky. Silueta má maximum 0,717 také u k = 5 (pro 4 je 0,658, pro 6 je 0,644). U našich dat se obě metody shodnou; u skutečných dat bývá loket zaoblený a silueta neurčitá. Počet shluků pak často rozhodne účel: marketing chce pět segmentů zákazníků, ne třicet sedm.
4. Kde k-means selhává
k-means rozdělí rovinu na oblasti nejbližších středů — každá je konvexní mnohoúhelník. Shluky, které tak nevypadají, najít nemůže. Klasický příklad jsou dva do sebe zaklesnuté měsíce:
Definice — DBSCAN
Nechť X ⊆ ℝd je konečná množina bodů, ε > 0 reálné číslo (poloměr) a m ∈ ℕ, m ≥ 1 (minimální počet bodů). Pro x, y ∈ X:
- ε-okolí bodu x je Nε(x) = {y ∈ X : ‖x − y‖ ≤ ε} (obsahuje i x samotný);
- x je jádrový, právě když |Nε(x)| ≥ m;
- y je z x přímo dosažitelný, právě když x je jádrový a y ∈ Nε(x);
- y je z x dosažitelný, právě když existují r ≥ 2 a body z1, …, zr ∈ X takové, že z1 = x, zr = y a zl+1 je přímo dosažitelný ze zl pro každé l = 1, …, r − 1;
- x a y jsou propojené, právě když existuje o ∈ X, ze kterého je dosažitelný x i y.
Shluk (Ester a kol., 1996) je neprázdná množina C ⊆ X, která splňuje
- maximalitu: ∀ x, y ∈ X : (x ∈ C ∧ y je dosažitelný z x) ⇒ y ∈ C;
- souvislost: ∀ x, y ∈ C : x a y jsou propojené.
Body z X, které nepatří do žádného shluku, jsou šum; nejádrový bod, který do nějakého shluku patří (leží v ε-okolí jádrového bodu), je okrajový. DBSCAN je algoritmus níže, který tyto shluky najde. Shluk tedy tvoří jádrové body, mezi kterými se dá přejít po krocích délky nejvýš ε přes další jádrové body, a k tomu všechny body v jejich okolí. Okrajový bod dosažitelný ze dvou různých shluků patří podle definice do obou; algoritmus ho přiřadí tomu, který ho najde dřív.
Shluk je tam, kde je hustě. DBSCAN jde od bodu k bodu, dokud má v okolí dost sousedů — jako když se po davu šíří zpráva od člověka k člověku. Počet shluků si určí sám a umí říct „tenhle bod nepatří nikam“. Za to potřebuje rozumně zvolit ε, a když mají shluky různou hustotu, jedno ε nesedí všem.
pro každý bod x, který ještě nemá značku:
když |N_ε(x)| < m: označ x jako šum; pokračuj dalším bodem
založ nový shluk C a dej do něj x
fronta ← N_ε(x)
dokud fronta není prázdná:
vyber z fronty bod y
když y je označený jako šum: dej ho do C # okrajový bod
když y už má shluk: pokračuj
dej y do C
když |N_ε(y)| ≥ m: přidej N_ε(y) do fronty # dál šíří jen jádrové body
k-means rozřízne měsíce šikmým řezem napříč oběma a správně zařadí jen 73,7 % bodů. DBSCAN s ε = 0,2 a m = 5 najde dva shluky, které přesně odpovídají měsícům, a žádný bod neoznačí za šum.
Definice — shoda shluků se skutečnými skupinami
Nechť n ≥ 1 je počet bodů, G1, …, Gq ⊆ {1, …, n} skutečné skupiny (navzájem disjunktní, se sjednocením {1, …, n}) a C1, …, Cp ⊆ {1, …, n} nalezené shluky (navzájem disjunktní; indexy mimo všechny shluky jsou šum). Shoda nalezených shluků se skupinami je číslo
shoda = 1/n ∑l=1p maxh ∈ {1, …, q} |Cl ∩ Gh| ∈ [0, 1].
Je to podíl bodů, které leží ve shluku spolu s většinou své skupiny — každý shluk „připíšeme“ skupině, které má v sobě nejvíc, a ostatní jeho body počítáme jako chybu; body označené za šum se také počítají jako chyba. Míra má smysl, jen když skutečné skupiny známe (tady víme, který bod je z kterého měsíce). Pro k-means vyšlo 221 z 300 bodů, tedy 221/300 ≈ 73,7 %. U dvou stejně velkých skupin dá i zcela náhodné rozdělení kolem 50 % — tohle je výchozí laťka, ne nula.
5. Prokletí dimenze
Zatím jsme měli body v rovině a viděli jsme je. Zákazník ale bývá popsaný stovkou čísel a obrázek tisíci pixelů. Ve vysokých dimenzích se navíc děje něco, co intuice z roviny nečeká.
Definice — prokletí dimenze
Prokletí dimenze (Richard Bellman, 1957) není jedna matematická věta, ale souhrnný název pro jevy, kvůli kterým metody fungující v malém počtu rozměrů d selhávají ve velkém. Pro body v jednotkové krychli [0, 1]d jsou to hlavně tyto tři:
- objem roste exponenciálně: pokrýt krychli mřížkou s krokem h ∈ (0, 1), 1/h ∈ ℕ, vyžaduje (1/h)d bodů — pro h = 0,1 a d = 10 deset miliard;
- data jsou řídká: krychle o hraně r ∈ (0, 1) zabírá podíl rd objemu, takže okolí, ve kterém leží 10 % rovnoměrně rozložených bodů, musí mít hranu r s rd = 0,1 — pro d = 10 je to r ≈ 0,79, „okolí“ tedy zabírá skoro celý rozsah každé souřadnice;
- vzdálenosti se koncentrují: pro dva nezávislé rovnoměrně rozložené body x, y ∈ [0, 1]d klesá podíl směrodatné odchylky a střední hodnoty ‖x − y‖2 k nule jako 1/√d (výpočet níže), takže všechny vzdálenosti jsou si relativně čím dál podobnější.
Vezmeme 500 náhodných bodů v krychli a pro jeden z nich porovnáme nejvzdálenějšího a nejbližšího souseda. Ve dvou rozměrech je nejvzdálenější soused průměrně 75,9× dál než nejbližší. V deseti rozměrech už jen 3,57×, ve stu 1,41× a v tisíci 1,11×. Všichni jsou od všech skoro stejně daleko, takže „nejbližší“ ztrácí smysl — a s ním metody, které na vzdálenostech stojí, včetně k-means.
Proč se to děje, se dá spočítat přesně. Vezměme dva nezávislé body x, y rovnoměrně rozložené v krychli [0, 1]d a čtverec jejich vzdálenosti ‖x − y‖2 = ∑r=1d (xr − yr)2. Je to součet d nezávislých stejně rozdělených sčítanců, a tak jeho střední hodnota i rozptyl rostou s d lineárně:
σ/E = √7d/180/d/6 = √1,4/d
- σ/E
- směrodatná odchylka ‖x − y‖2 dělená jeho střední hodnotou (relativní rozptyl) — jak moc se vzdálenosti mezi různými dvojicemi bodů liší vůči své typické velikosti; jen to rozhoduje, jestli „nejbližší“ a „nejvzdálenější“ jsou různé věci
- d/6
- střední hodnota ‖x − y‖2 — každá souřadnice přidá v průměru 1/6, takže typická vzdálenost roste jako √d
- √7d/180
- směrodatná odchylka — rozptyl roste také lineárně (7/180 za souřadnici), ale odchylka je jeho odmocnina, roste tedy jen jako √d: nezávislé výkyvy jednotlivých souřadnic se navzájem zčásti vyruší
- √1,4/d
- výsledek klesá jako 1/√d: pro d = 2 je 0,84, pro 10 je 0,37, pro 100 je 0,12 a pro 1 000 už jen 0,037 — vzdálenosti se k sobě stahují
Příklad — odkud jsou čísla 1/6 a 7/180
Rozdíl t = xr − yr dvou nezávislých rovnoměrných čísel z [0, 1] má trojúhelníkovou hustotu 1 − |t| na [−1, 1]. Proto E[t2] = 2∫01 t2(1 − t) dt = 2(1/3 − 1/4) = 1/6 a E[t4] = 2(1/5 − 1/6) = 1/15. Rozptyl jednoho sčítance t2 je E[t4] − E[t2]2 = 1/15 − 1/36 = 7/180. Střední hodnoty i rozptyly nezávislých sčítanců se sčítají, takže pro d souřadnic dostaneme střední hodnotu d/6 a rozptyl 7d/180, tedy směrodatnou odchylku √7d/180. Poměr (barvy podle vzorce výše):
√7d/180 · 6/d = √36 · 7/180 d = √1,4/d.
Tohle je náš vlastní výpočet pro rovnoměrná data; stejný jev (koncentraci vzdáleností) pro mnohem obecnější rozdělení dokázali Beyer a kol. (1999) v práci „When is ‚nearest neighbor‘ meaningful?“.
Skutečná data mají naštěstí obvykle mnohem menší „vnitřní“ dimenzi: fotky obličejů se liší v pár desítkách vlastností (natočení, osvětlení, výraz), ne v milionu pixelů nezávisle. Snížení dimenze se snaží ty podstatné směry najít.
6. Analýza hlavních komponent
Definice — analýza hlavních komponent (PCA)
Nechť n ≥ 2 a D ≥ 1 jsou přirozená čísla, x1, …, xn ∈ ℝD body s průměrem x̄ = 1/n ∑i=1n xi a Σ ∈ ℝD×D jejich kovarianční matice (definice níže). Matice Σ je symetrická a pozitivně semidefinitní, má proto vlastní čísla λ1 ≥ λ2 ≥ … ≥ λD ≥ 0 a k nim vlastní vektory w1, …, wD ∈ ℝD, které jsou ortonormální: Σwr = λrwr, ‖wr‖ = 1 a wr · ws = 0 pro r ≠ s. Pak
- r-tá hlavní komponenta (r = 1, …, D) je směr wr (při navzájem různých vlastních číslech je určen jednoznačně až na znaménko);
- snížení dimenze na q (q ∈ {1, …, D}) je zobrazení x ↦ (w1 · (x − x̄), …, wq · (x − x̄)) ∈ ℝq, tj. promítnutí vycentrovaného bodu na prvních q komponent;
- podíl vysvětleného rozptylu prvními q komponentami (pro Σ ≠ 0) je λ1 + … + λq/λ1 + … + λD.
Vlastní číslo λr je přitom rozptyl dat ve směru wr (věta níže), takže první komponenta je směr, ve kterém se data liší nejvíc.
PCA otočí souřadnice tak, aby první osa vedla směrem, ve kterém se data liší nejvíc, druhá kolmo na ni směrem dalšího největšího rozdílu a tak dál. Pak zahodíme osy, podél kterých se skoro nic neděje. Je to jako fotit hejno ptáků: z boku vidíte jeho tvar, zepředu jen chuchvalec — PCA hledá ten boční pohled.
Definice — kovarianční matice
Nechť n ≥ 2, D ≥ 1 a x1, …, xn ∈ ℝD jsou body (sloupcové vektory, xia je a-tá souřadnice bodu xi) s průměrem x̄ = 1/n ∑i=1n xi. Jejich (výběrová) kovarianční matice je matice Σ ∈ ℝD×D,
Σ = 1/n − 1 ∑i=1n (xi − x̄)(xi − x̄)T, tj. Σab = 1/n − 1 ∑i=1n (xia − x̄a)(xib − x̄b) pro a, b = 1, …, D.
Prvek Σab je tedy (skoro) průměrný součin odchylek a-té a b-té souřadnice od jejich průměrů. Na diagonále jsou rozptyly jednotlivých souřadnic, mimo ni kovariance: kladná, když obě souřadnice bývají současně nad průměrem (nebo současně pod ním). Dělí se n − 1, ne n, protože průměr byl odhadnut ze stejných dat (Besselova korekce).
w1 = arg max‖w‖ = 1 wTΣw
- w1
- směr první hlavní komponenty (na obrázku níže jantarová šipka)
- wTΣw
- rozptyl průmětů dat do směru w: průmět bodu je číslo w · (xi − x̄) a součet jeho čtverců dělený n − 1 (jako u Σ) vyjde přesně wTΣw; tohle je to „jak moc se data v tom směru liší“, co chceme zachovat
- arg max
- nehledáme největší rozptyl samotný, ale směr, ve kterém nastává — ten pak bude novou osou
- ‖w‖ = 1
- bez téhle podmínky by stačilo w natáhnout a „rozptyl“ by rostl nade všechny meze; jednotková délka dělá z w čistý směr
Věta — hlavní komponenty jsou vlastní vektory
Nechť D ≥ 1 a Σ ∈ ℝD×D je symetrická matice s největším vlastním číslem λ1. Pak funkce w ↦ wTΣw na množině {w ∈ ℝD : ‖w‖ = 1} nabývá maxima, toto maximum je rovno λ1 a nabývá se ve vlastním vektoru Σ k vlastnímu číslu λ1.
Důkaz. Maximum existuje, protože spojitá funkce na jednotkové sféře (uzavřené a omezené množině) maxima nabývá. Hledáme ho Lagrangeovou funkcí L = wTΣw − λ(wTw − 1). Gradient podle w je 2Σw − 2λw, a ten je nulový, právě když Σw = λw — w je vlastní vektor. Dosazením: wTΣw = λwTw = λ, takže rozptyl ve směru vlastního vektoru je jeho vlastní číslo a maximum dává vlastní vektor s největším λ. ∎ Protože je Σ symetrická, jsou její vlastní vektory navzájem kolmé a součet všech vlastních čísel je stopa Σ, tedy součet rozptylů všech souřadnic — odtud jmenovatel ve vzorci pro vysvětlený rozptyl.
První komponenta míří šikmo nahoru (0,61; 0,79): vyšší lidé bývají i těžší, takže hlavní rozdíl mezi lidmi je „celková velikost“. Vysvětluje 86,4 % rozptylu. Druhá, kolmá komponenta říká, kdo je na svou výšku těžší nebo lehčí, a nese zbylých 13,6 %. Kdybychom si o každém pamatovali jen jedno číslo — polohu na první komponentě — ztratili bychom necelou sedminu informace o rozptylu.
Příklad — PCA výšky a váhy ručně
Průměr 150 lidí je 171,9 cm a 71,5 kg; kovarianční matice (v cm2, cm · kg a kg2) vyšla
Σ = ( 63,84 54,95 ; 54,95 92,31 ).
Vlastní čísla matice 2 × 2 jsou kořeny λ2 − (stopa) λ + det = 0. Stopa = 63,84 + 92,31 = 156,14, det = 63,84 · 92,31 − 54,952 ≈ 2 873,3, a tak λ = 78,07 ± √78,072 − 2 873,3 = 78,07 ± 56,76, tedy λ1 = 134,83 a λ2 = 21,31.
Vlastní vektor k λ1: z prvního řádku (63,84 − λ1)w1 + 54,95 w2 = 0 vyhovuje (54,95; 70,99); vydělením délkou 89,77 dostaneme w1 = (0,61; 0,79) a w1TΣw1 = λ1 = 134,83 (barvy podle vzorce výše). Vysvětlený rozptyl 134,83/156,14 = 86,4 %. Směrodatná odchylka podél první komponenty je √134,83 ≈ 11,6, podél druhé √21,31 ≈ 4,6 (smíšené jednotky, protože osy míchají centimetry s kilogramy — v praxi se proto souřadnice s různými jednotkami před PCA často standardizují).
U 64 rozměrů už vlastní čísla ručně nepočítáme. Jednoduchý postup, který používá i náš výpočet, je mocninná metoda: opakované násobení maticí natočí libovolný vektor do směru s největším vlastním číslem.
Σ ← kovarianční matice vycentrovaných dat
pro c = 1 … q:
v ← libovolný nenulový vektor
opakuj 500×:
v ← Σv / ‖Σv‖ # složka s největším λ roste nejrychleji
λ_c ← vᵀΣv; w_c ← v
Σ ← Σ − λ_c · w_c w_cᵀ # deflace: nalezený směr z matice odečti
Teď těžší data. Ručně psané číslice 8 × 8 pixelů: každá je vektor 64 čísel. Vyrobili jsme si 300 syntetických — deset vzorů, každý náhodně posunutý o pixel, rozmazaný, různě silný a se šumem:
První dvě hlavní komponenty vysvětlují jen 24,0 % rozptylu a deset komponent 64,4 %. Rozptyl je rozprostřený do mnoha směrů — posunutí o pixel změní skoro všechny pixely najednou a žádná přímka to nevystihne.
7. t-SNE: mapa sousedství
Definice — t-SNE
Nechť n ≥ 2, D ≥ 1, x1, …, xn ∈ ℝD jsou body a u > 0 zvolená perplexita. t-SNE (t-distributed stochastic neighbor embedding; van der Maaten a Hinton, 2008) přiřadí bodům xi body mapy y1, …, yn ∈ ℝ2 takto:
- z bodů xi a perplexity u spočte podobnosti pij ≥ 0 pro i ≠ j se součtem ∑i≠j pij = 1 (další definice) — pij vyjadřuje, nakolik jsou i a j sousedé v původním prostoru;
- pro body mapy definuje podobnosti se Studentovým jádrem (Studentovo rozdělení s jedním stupněm volnosti) qij = (1 + ‖yi − yj‖2)−1/∑k≠l (1 + ‖yk − yl‖2)−1 pro i ≠ j;
- body y1, …, yn volí tak, aby byla co nejmenší Kullbackova–Leiblerova divergence C(y1, …, yn) = KL(P ‖ Q) = ∑i≠j pij ln pij/qij (sčítají se jen dvojice s pij > 0); minimum hledá gradientním sestupem z náhodného startu, takže najde jen lokální minimum.
t-SNE tedy rozmístí body v rovině tak, aby si sousedé z původního prostoru zůstali sousedy i na mapě.
PCA se snaží zachovat velké vzdálenosti, t-SNE malé: chce, aby každý bod měl na mapě za sousedy ty, které měl za sousedy i v 64 rozměrech. Jak daleko jsou od sebe vzdálené skupiny, mu je skoro jedno. Studentovo rozdělení má „tlusté konce“, takže body, které sousedy nejsou, smí odstrčit hodně daleko — proto vznikají ostře oddělené ostrůvky.
Definice — podobnosti v původním prostoru a perplexita
Nechť n ≥ 2, x1, …, xn ∈ ℝD a pro každé i = 1, …, n nechť σi > 0 (šířka jádra bodu i). Pro i ≠ j položme
pj|i = exp(−‖xi − xj‖2/2σi2)/∑k≠i exp(−‖xi − xk‖2/2σi2)
— pravděpodobnost, že si bod i vybere za souseda bod j; pro pevné i tvoří čísla Pi = (pj|i)j≠i rozdělení pravděpodobnosti. Jeho entropie a perplexita jsou
H(Pi) = −∑j≠i pj|i log2 pj|i, Perp(Pi) = 2H(Pi).
Šířka σi se pro každý bod zvlášť najde půlením intervalu tak, aby Perp(Pi) = u (zadaná perplexita, u nás 30). Nakonec se podobnosti symetrizují:
pij = pj|i + pi|j/2n pro i ≠ j,
takže pij = pji a ∑i≠j pij = 1 (každé Pi má součet 1, dohromady 2n). Kdyby bod měl přesně 30 stejně pravděpodobných sousedů a ostatní nulové, vyšlo by H = log2 30 a perplexita 30 — perplexita je tedy „efektivní počet sousedů“. V hustém místě tak vyjde σi malé, v řídkém velké.
C = ∑i≠j pij ln pij/qij,
qij = (1 + ‖yi − yj‖2)−1/∑k≠l (1 + ‖yk − yl‖2)−1
- C = KL(P ‖ Q)
- cena mapy — gradientní sestup posouvá body yi v rovině tak, aby klesala; je nulová, jen když Q = P
- pij
- váha dvojice podle toho, jak moc jsou i a j sousedy v původních 64 rozměrech — dvojice, které sousedy nejsou, mají pij ≈ 0 a skoro nic nestojí, ať jsou na mapě kdekoli; proto t-SNE nehlídá velké vzdálenosti
- ln pij/qij
- logaritmus toho, kolikrát jsou si body na mapě „méně blízko“, než by měly být; kladné a velké, když sousedy z originálu mapa roztrhla — přesně tuhle chybu cena trestá nejvíc
- (1 + ‖yi − yj‖2)−1
- Studentovo jádro s tlustými konci: na vzdálenost 3 dává 1/1 + 32 = 0,1, Gaussovo exp(−32) ≈ 0,000 12 — 810× méně. Středně vzdálené body tak mohou být na mapě daleko, aniž by to moc stálo, a ostrůvky se od sebe oddělí
- ∑k≠l …
- normalizace přes všechny dvojice — aby Q bylo rozdělení pravděpodobnosti jako P a dala se porovnat
Rozdíl změříme jednoduše: pro každý bod se podíváme na jeho pět nejbližších sousedů a spočítáme, kolik z nich je stejná číslice. V původních 64 rozměrech je to 77,9 %. Na mapě PCA jen 47,8 % — číslice se překrývají. Na mapě t-SNE 79,1 %, tedy prakticky stejně jako v původním prostoru: t-SNE sousedství zachovala.
Definice — čistota sousedů
Nechť n ≥ 6, y1, …, yn ∈ ℝq jsou body zobrazení (mapy nebo původního prostoru) a t1, …, tn jejich skutečné třídy (u nás číslice 0–9). Pro každé i nechť N5(i) ⊆ {1, …, n} ∖ {i}, |N5(i)| = 5, je množina indexů pěti bodů nejbližších k yi (bez něj samotného; shody vzdáleností se rozhodnou libovolně). Čistota sousedů je číslo
čistota = 1/n ∑i=1n |{j ∈ N5(i) : tj = ti}|/5 ∈ [0, 1],
tedy průměrný podíl sousedů se stejnou třídou. Bod, jehož pět sousedů jsou tři stejné číslice a dvě jiné, přispěje 3/5. Míra vůbec nepoužívá vzdálenosti mezi ostrůvky — měří jen to, na čem t-SNE záleží.
Na mapě t-SNE si ale všimněte, že jedna číslice netvoří jeden ostrůvek, ale několik. t-SNE věrně ukazuje, co je blízko v pixelech — a dvojka posunutá o pixel doprava má s jinými posunutými dvojkami společné jiné pixely než dvojka na svém místě. Ostrůvky odpovídají číslici a posunu: 66,4 % sousedů na mapě má stejnou číslici i stejný posun, stejně jako v původním prostoru (66,5 %). Chyba tedy není v t-SNE, ale v popisu obrázku pixely. Proto se pro obrázky používají konvoluční sítě, kterým posun o pixel skoro nevadí.
Mapa t-SNE navíc svádí k chybným závěrům. Velikost ostrůvků a vzdálenosti mezi nimi nic neznamenají — t-SNE velikosti vyrovnává: husté shluky roztáhne, řídké smrští. Výsledek závisí na perplexitě a na náhodném startu. A na nové body se mapa rozšířit nedá; je to nástroj na prohlížení, ne model. Novější metoda UMAP (2018) dává podobné obrázky rychleji a o něco lépe zachová i celkové rozložení.
8. K čemu se to používá
- Segmentace zákazníků — k-means nad nákupním chováním, pak marketing pro každý segment zvlášť.
- Biologie — t-SNE a UMAP jsou standardní obrázek v analýze jednotlivých buněk: každá tečka je buňka, ostrůvky jsou typy buněk.
- Komprese a předzpracování — PCA zmenší počet příznaků před učením jiného modelu a odstraní šum v málo důležitých směrech.
- Zkoumání neuronových sítí — vnitřní reprezentace slov nebo obrázků mají stovky rozměrů; t-SNE z nich udělá mapu, na které je vidět, co síť považuje za podobné.
- Kvantizace — k-means vybere 256 barev, kterými se nejlépe nahradí miliony barev fotky; stejný trik zmenšuje váhy neuronových sítí.
9. Shrnutí
- k-means střídá přiřazení k nejbližšímu středu a přesun středu do průměru; inercie nikdy neroste, ale algoritmus může uvíznout v lokálním optimu.
- k-means++ volí vzdálené počáteční středy: na našich datech našel nejlepší řešení v 88 % běhů proti 56 % s náhodným startem.
- Počet shluků se volí loktem inercie nebo siluetou; obě ukázaly k = 5.
- k-means hledá jen konvexní shluky; na dvou měsících zařadil správně 73,7 % bodů, hustotní DBSCAN všechny.
- Ve vysokých dimenzích jsou všechny body skoro stejně daleko — v tisíci rozměrech je nejvzdálenější soused jen 1,11× dál než nejbližší.
- PCA najde směry největšího rozptylu; t-SNE zachová sousedství. U číslic měla mapa t-SNE správných sousedů 79,1 %, PCA 47,8 %.
Chcete si to osahat? Nechte AI agenta pustit k-means na fotku a zmenšit ji na osm barev — a pak zkuste, kolik barev už oko nerozezná od originálu.
Máte na to jiný názor? Napište na support@coden-app.com.