Skryté Markovove modely: Viterbiho algoritmus a nepoctivé kasíno
Skrytý Markovov model, tri úlohy podľa Rabinera, dopredný algoritmus, Viterbiho algoritmus, aposteriórne dekódovanie a Baumov–Welchov algoritmus — na kasíne, ktoré občas potajomky vymení kocku za falošnú.
Séria Základy AI Diel 39 z 52
- Mapa umelej inteligencie: čo je čo a ako to do seba zapadá
- Stručná história umelej inteligencie: od Turinga po jazykové modely
- Dáta, model, tréning, inferencia: základné pojmy na jednom príklade
- Ako čítať matematický zápis: symboly, indexy, sumy a kvantifikátory
- Množiny a relácie: stavebnica, z ktorej sa skladajú definície v AI
- Funkcie a zobrazenia: prečo je každý model v AI funkcia
- Logika a dôkazy: pravidlá, podľa ktorých sa v AI uvažuje
- Grafy a stromy: štruktúra, na ktorej stojí hľadanie aj neurónové siete
- Lineárna algebra pre strojové učenie: vektory, matice a prečo AI hlavne násobí
- Derivácie, gradient a reťazové pravidlo: ako model zistí, ktorým smerom sa učiť
- Gradientný zostup: ako sa model učí
- Čo je pravdepodobnosť: od hodu kockou ku Kolmogorovovým axiómam
- Podmienená pravdepodobnosť a Bayesova veta: ako zmeniť odhad, keď sa dozviete niečo nové
- Náhodná premenná a distribučná funkcia: jedna funkcia, ktorá o rozdelení povie všetko
- Funkcia hustoty a pravdepodobnostná funkcia: prečo má spojitá premenná v bode pravdepodobnosť nula
- Stredná hodnota, rozptyl a kovariancia: kde rozdelenie leží, aké je široké a čo s čím súvisí
- Prehľad pravdepodobnostných rozdelení: Bernoulliho, binomické, Poissonovo, rovnomerné, normálne a exponenciálne
- Zákon veľkých čísel a centrálna limitná veta: prečo sa priemery správajú tak predvídateľne
- Štatistika a odhady parametrov: maximálna vierohodnosť, MAP a intervaly spoľahlivosti
- Teória informácie: entropia, krížová entropia a KL divergencia — odkiaľ sa berú stratové funkcie
- Prehľadávanie stavového priestoru: BFS, DFS, UCS a A* s animáciami
- Hry a protivník: minimax, alfa-beta orezávanie a Monte Carlo tree search
- Splňovanie obmedzujúcich podmienok: backtracking, propagácia obmedzení a AC-3 na sudoku a mape krajov
- Logika a znalostné systémy: dopredné a spätné reťazenie, rezolúcia a expertné systémy
- Plánovanie: STRIPS, svet kociek, heuristiky z relaxácie a plánovanie v AI agentoch
- Lokálne hľadanie a simulované žíhanie: obchodný cestujúci cez krajské mestá
- Genetické algoritmy: populácia, kríženie, mutácia a výber na batohu na výlet
- Evolučné stratégie a genetické programovanie: od pravidla jednej pätiny po Keplerov zákon
- Optimalizácia mravčou kolóniou: ako feromónová stopa nájde krátku cestu
- Optimalizácia rojom častíc: zotrvačnosť, vlastná skúsenosť a skúsenosť roja
- Neuroevolúcia: evolúcia váh aj tvaru neurónových sietí a algoritmus NEAT
- Fuzzy množiny a funkcie príslušnosti: ako zapísať „trochu teplo“
- Fuzzy logika a pravdepodobnosť: prečo „trochu teplo“ neznamená „pravdepodobne teplo“
- Fuzzy logika: t-normy, implikácie a pravidlá AK–TAK
- Fuzzy riadenie: Mamdani a Sugeno od ventilátora po kyvadlo na vozíku
- Fuzzy zhlukovanie: algoritmus fuzzy c-means a body medzi zhlukmi
- Neuro-fuzzy systémy (ANFIS): fuzzy pravidlá, ktoré sa učia z dát
- Markovove reťazce: prechodová matica, stacionárne rozdelenie a PageRank
- Skryté Markovove modely: Viterbiho algoritmus a nepoctivé kasíno
- Bayesovské siete: prečo je tráva mokrá a čo z toho vyplýva pre postrekovač
- Kalmanov filter: ako z nepresných meraní odhadnúť, kde auto je a ako rýchlo ide
- Druhy strojového učenia: s učiteľom, bez učiteľa, s čiastočným učiteľom a ďalšie
- Prompty, kontext a RAG: ako modelu dať správne informácie
- Variačné autoenkodéry (VAE): nové obrázky zo spojitého latentného priestoru
- Generatívne adversariálne siete (GAN): falšovateľ proti detektívovi
- Difúzne modely: ako sa z čistého šumu stane obrázok
- Markovove rozhodovacie procesy: stavy, akcie, odmeny a Bellmanove rovnice
- Q-learning a DQN: učenie hodnoty akcií od tabuľky po neurónovú sieť
- Policy gradient a PPO: učenie priamo stratégie
- Ako funguje AI agent: jazykový model v slučke s nástrojmi
- Programovanie s AI agentmi: zadanie, testy a kontrola
- Vyhodnocovanie a bezpečnosť AI systémov: ako merať a ako strážiť
Celá osnova série Hotovo: 52 z 83 tém
- Čo je skrytý Markovov model a ako sa z pozorovaní vypočíta ich pravdepodobnosť bez prechádzania všetkých ciest.
- Ako Viterbiho algoritmus nájde najpravdepodobnejšie skryté stavy a kde sa mýli.
- Ako sa model naučí parametre len z pozorovaní a koľko dát na to potrebuje.
Čo sa hodí vedieť vopred: Markovove reťazce: prechodová matica, stacionárne rozdelenie a PageRank
V minulom diele sme stav reťazca videli: dnes svieti slnko, zajtra prší. Často však vidíme len jeho prejavy. Mikrofón zachytí zvukovú vlnu, nie slovo, ktoré ju vytvorilo. Sekvenátor prečíta písmená DNA, nie to, kde začína gén. A v kasíne vidíme, čo padlo, nie ktorou kockou krupiér hádže. Skryté Markovove modely sú reťazce, ktorých stavy nevidíme — a algoritmy, ktorými sa dá aj tak zistiť, čo sa deje vnútri. Celé desaťročia na nich stálo rozpoznávanie reči.
Nadväzuje na diel Markovove reťazce.
1. Nepoctivé kasíno
Klasický učebnicový príklad (Durbin a kol., 1998): krupiér hádže buď poctivou kockou, alebo falošnou, na ktorej padá šestka s pravdepodobnosťou 1/2 a ostatné čísla s 1/10. Po každom hode s pravdepodobnosťou 0,05 vymení poctivú za falošnú a s pravdepodobnosťou 0,1 falošnú späť za poctivú. Výmenu nevidíme. Vidíme len rad čísel — v našom pokuse 300 hodov, ktoré začínajú takto:
163665521623524236522511663566613666222461626262162666626516…
Pýtame sa: hrá sa tu poctivo? A ak nie, kedy presne bola v hre falošná kocka?
2. Skrytý Markovov model
Definícia — skrytý Markovov model
Nech N, M ≥ 1 sú celé čísla, S = {1, …, N} množina skrytých stavov a V = {1, …, M} množina pozorovateľných symbolov. Ďalej nech
- π = (π1, …, πN) ∈ ℝ1×N je rozdelenie pravdepodobnosti na S (πi ≥ 0, ∑i πi = 1) — počiatočné rozdelenie;
- A = (aij) ∈ ℝN×N je stochastická matica — prechodová matica;
- B = (bi(o))i ∈ S, o ∈ V ∈ ℝN×M je stochastická matica — emisné pravdepodobnosti.
Skrytý Markovov model (HMM) s parametrami λ = (π, A, B) je dvojica postupností náhodných premenných X1, X2, … : Ω → S (skryté stavy) a O1, O2, … : Ω → V (pozorovania) na pravdepodobnostnom priestore (Ω, 𝓕, P), pre ktorú platí:
- (Xt)t ≥ 1 je homogénny Markovov reťazec s počiatočným rozdelením P(X1 = i) = πi a prechodovou maticou A, t. j. aij = P(Xt+1 = j | Xt = i);
- pre každé T ≥ 1, t ∈ {1, …, T}, o ∈ V a všetky hodnoty x1, …, xT ∈ S a os ∈ V (s ≠ t), pre ktoré má podmienka kladnú pravdepodobnosť, P(Ot = o | X1 = x1, …, XT = xT, Os = os pre s ∈ {1, …, T} ∖ {t}) = bxt(o).
Slovami: skryté stavy sa menia ako obyčajný Markovov reťazec a pozorovanie v čase t závisí len od stavu Xt — nie od ostatných stavov ani od ostatných pozorovaní. Pozorujeme len O1, O2, …, stavy Xt nie.
Za oponou beží obyčajný Markovov reťazec — kocka sa mení podľa matice A. My vidíme len to, čo z každého stavu „vypadne“: hod podľa pravdepodobností B. Šestka je pri falošnej kocke päťkrát pravdepodobnejšia než akékoľvek iné číslo, ale môže padnúť aj na poctivej. Jednotlivý hod preto nič neprezradí — prezradí to až vzor v celom rade.
Z definície vyplýva, aká pravdepodobná je jedna konkrétna „história“: postupnosť kociek x = (x1, …, xT) spolu s hodmi O = (O1, …, OT).
P(x, O | λ) = πx1 bx1(O1) · ∏t=2T axt−1 xt bxt(Ot)
- πx1
- prvá kocka nemá predchodcu, z ktorého by sa na ňu prešlo — jej pravdepodobnosť dáva počiatočné rozdelenie
- axt−1 xt
- každá ďalšia kocka závisí len od tej predchádzajúcej (Markovova vlastnosť), takže za každý krok stačí jedno číslo z matice A
- bxt(Ot)
- hod závisí len od kocky, ktorou sa práve hádže — berieme pravdepodobnosť čísla, ktoré naozaj padlo
- ∏t=2T
- vo všeobecnosti by sa násobili pravdepodobnosti podmienené celou minulosťou (reťazové pravidlo); oba predpoklady nezávislosti z definície ich skrátia na tieto miestne čísla, a preto je celok prostý súčin
Príklad — dve histórie prvých troch hodov
Náš rad začína hodmi 1, 6, 3. Označme P poctivú a F falošnú kocku. História „trikrát falošná“:
P(FFF, 1, 6, 3) = 0,5 · 0,1 · 0,9 · 0,5 · 0,9 · 0,1 = 0,002025,
história „trikrát poctivá“:
P(PPP, 1, 6, 3) = 0,5 · 1/6 · 0,95 · 1/6 · 0,95 · 1/6 = 0,002089
(farby podľa vzorca vyššie: počiatočné rozdelenie, emisie, prechody). Poctivá história vyjde o chlp pravdepodobnejšia: šestka na falošnej kocke síce dostane 0,5 namiesto 1/6, ale jednotka a trojka len 0,1 namiesto 1/6. (V simulácii sa pritom všetky tri hody hádzali falošnou kockou — z troch hodov sa to spoznať nedá.)
Lawrence Rabiner v slávnom prehľade z roku 1989 zhrnul, čo sa s takým modelom dá robiť, do troch úloh: ohodnotenie (aký pravdepodobný je pozorovaný rad?), dekódovanie (aké skryté stavy za ním najskôr boli?) a učenie (aké parametre má model, keď poznáme len pozorovania?). Na každú existuje elegantný algoritmus.
3. Aký pravdepodobný je rad: dopredný algoritmus
Pravdepodobnosť pozorovaného radu je súčet cez všetky možné postupnosti skrytých stavov. Tých je pre 300 hodov a dve kocky 2300 ≈ 2 · 1090 — viac, než je atómov vo vesmíre. Priamo to sčítať nejde. Markovova vlastnosť však dovolí počítať postupne.
Príklad — pravdepodobnosť troch hodov súčtom cez všetky histórie
Pravdepodobnosť pozorovania je súčet združenej pravdepodobnosti cez všetky možné histórie: P(O | λ) = ∑x P(x, O | λ). Pre hody 1, 6, 3 ich je 23 = 8:
| História | P(x, O) |
|---|---|
| PPP | 0,002089 |
| PPF | 0,000066 |
| PFP | 0,000035 |
| PFF | 0,000188 |
| FPP | 0,000132 |
| FPF | 0,000004 |
| FFP | 0,000375 |
| FFF | 0,002025 |
| súčet | 0,004913 |
Každá história stojí 2T − 1 = 5 násobení, dohromady 8 · 5 = 40. Pre T hodov je to (2T − 1) · 2T — pri 300 hodoch nepredstaviteľne veľa.
Algoritmus — dopredný algoritmus
Vstup: skrytý Markovov model λ = (π, A, B) so stavmi S = {1, …, N} a symbolmi V; pozorovaná postupnosť O = (O1, …, OT) ∈ VT, T ≥ 1.
Výstup: P(O | λ) = P(O1, …, OT) a dopredné premenné
αt(j) = P(O1, …, Ot, Xt = j | λ), t = 1, …, T, j ∈ S.
- Inicializácia: pre každé j ∈ S polož α1(j) = πj bj(O1).
- Indukcia: pre t = 1, …, T − 1 a každé j ∈ S polož αt+1(j) = [∑i=1N αt(i) aij] · bj(Ot+1).
- Ukončenie: po spracovaní času T vráť P(O | λ) = ∑j=1N αT(j).
Algoritmus skončí po T − 1 krokoch indukcie; každý stojí O(N2) operácií, spolu teda O(N2 T) namiesto O(T · NT) pri sčítaní cez všetky histórie. Aby čísla nepodtiekli, v každom čase t sa vypočíta ct = ∑j αt(j) (s už normalizovaným αt−1 v indukcii), αt(j) sa nahradí αt(j)/ct a vracia sa log P(O | λ) = ∑t=1T log ct.
Nemusíte sledovať každú možnú históriu zvlášť. Stačí si po každom hode pamätať dve čísla: „aké pravdepodobné je všetko, čo som zatiaľ videl, a že teraz je v hre poctivá kocka“ — a to isté pre falošnú. Z nich sa vypočítajú čísla pre ďalší hod. Všetky histórie, ktoré končia rovnakým stavom, sa zlúčia do jedného čísla.
αt+1(j) = ∑i αt(i) aij · bj(Ot+1)
- αt(i)
- všetko, čo vieme o minulosti: pravdepodobnosť doterajších hodov a toho, že teraz je v hre kocka i; v tomto jedinom čísle sú zlúčené všetky histórie končiace v i
- aij
- krok reťazca z i do j; vďaka Markovovej vlastnosti nezáleží na tom, ako sme sa do i dostali
- ∑i
- nevieme, ktorou kockou sa hádzalo naposledy, a do j sa dá dôjsť z ktorejkoľvek — preto sčítavame cez všetky možnosti (histórie sú navzájom nezlučiteľné javy)
- bj(Ot+1)
- nový hod musí kocka j naozaj vygenerovať; nezávisí od i, a tak sa dá vybrať pred súčet
Príklad — dopredný algoritmus na hodoch 1, 6, 3
Štart: α1(P) = 0,5 · 1/6 = 0,0833, α1(F) = 0,5 · 0,1 = 0,0500. Druhý hod je šestka (farby podľa vzorca vyššie):
α2(P) = (0,0833 · 0,95 + 0,0500 · 0,1) · 1/6 = 0,0140,
α2(F) = (0,0833 · 0,05 + 0,0500 · 0,9) · 0,5 = 0,0246.
| t | hod | αt(P) | αt(F) | súčet = P(O1, …, Ot) | ct |
|---|---|---|---|---|---|
| 1 | 1 | 0,0833 | 0,0500 | 0,133333 | 0,1333 |
| 2 | 6 | 0,0140 | 0,0246 | 0,038611 | 0,2896 |
| 3 | 3 | 0,0026 | 0,0023 | 0,004913 | 0,1273 |
Súčet v poslednom riadku je presne súčet ôsmich histórií z predchádzajúceho príkladu, len namiesto 40 násobení stačilo 2 + 2 · 6 = 14. Posledný stĺpec ct = P(Ot | O1, …, Ot−1) je normalizačná konštanta zo škálovania: aký pravdepodobný bol hod t vzhľadom na tie predchádzajúce. Ich súčin je P(O | λ), takže log P(O | λ) = ∑t log ct.
Prečo logaritmy? Pri 3 000 hodoch vyjde P(O | λ) okolo 10−2 278, a najmenšie kladné číslo, ktoré počítač v bežnej dvojitej presnosti (IEEE 754) uloží, je asi 4,9 · 10−324. Bez škálovania by α podtieklo na nulu.
def dopredu(hody, pi, A, B):
alfa = pi * B[:, hody[0]]
logP = 0.0
for t in range(len(hody)):
if t > 0:
alfa = (alfa @ A) * B[:, hody[t]] # súčet cez i, potom emisia
c = alfa.sum() # c_t = P(O_t | O_1, …, O_t−1)
alfa = alfa / c # škálovanie: α_t sa teraz sčíta na 1
logP += np.log(c)
return logP # log P(O | λ)
Pre našich 300 hodov vyjde P(hody | model kasína) ≈ 10−230,03. Keby sa celý čas hralo poctivo, bola by pravdepodobnosť (1/6)300 ≈ 10−233,45. Model s občasnou falošnou kockou vysvetľuje pozorované hody asi 2 600-krát lepšie — silný dôkaz, že sa tu podvádza, hoci žiadny jednotlivý hod podvod neprezradí.
Definícia — pomer vierohodností (Bayesov faktor)
Nech (Ω, 𝓕, P) je pravdepodobnostný priestor, M1, M2 ∈ 𝓕 sú javy „platí model 1“ a „platí model 2“ s P(M1) > 0, P(M2) > 0 a O ∈ 𝓕 je jav „pozorovali sme dáta“ s P(O | M2) > 0. Bayesov faktor modelu M1 proti M2 je číslo
K = P(O | M1)/P(O | M2),
t. j. podiel vierohodností dát v oboch modeloch. K > 1 znamená, že dáta sú pravdepodobnejšie v modeli M1. Ak je navyše P(O) > 0, vyplýva z Bayesovej vety napísanej pre oba modely a vydelenej (P(O) sa skráti):
P(M1 | O)/P(M2 | O) = P(O | M1)/P(O | M2) · P(M1)/P(M2)
- P(M1 | O)/P(M2 | O)
- pomer šancí po pozorovaní — to, čo nás zaujíma: o koľko viac veríme podvodu než poctivej hre, keď sme hody videli
- P(O | M1)/P(O | M2)
- Bayesov faktor — jediné miesto, kadiaľ do vzorca vstupujú dáta; obe vierohodnosti vypočíta dopredný algoritmus. Menovateľ P(O) z Bayesovej vety sa pri delení skráti, a preto ho netreba poznať
- P(M1)/P(M2)
- pomer šancí vopred — kto kasínu vopred verí, potrebuje silnejší dôkaz; dáta ho len prenásobia
Výpočet. log10 K = −230,03 − (−233,45) = 3,42 (z nezaokrúhlených hodnôt 3,413), teda K ≈ 103,413 ≈ 2 590, zaokrúhlene 2 600. Kto vopred považoval podvod a poctivú hru za rovnako pravdepodobné (pomer šancí 1), má po 300 hodoch šance 2 600 · 1 = 2 600 : 1 v prospech podvodu. Podľa bežne používanej stupnice Kassa a Rafteryho (1995) je Bayesov faktor nad 150 „veľmi silný“ dôkaz.
4. Kedy sa podvádzalo: Viterbiho algoritmus
Algoritmus — Viterbiho algoritmus (1967)
Vstup: skrytý Markovov model λ = (π, A, B) so stavmi S = {1, …, N}; pozorovanie O = (O1, …, OT) ∈ VT, T ≥ 1.
Výstup: najpravdepodobnejšia postupnosť skrytých stavov a jej pravdepodobnosť
x* = argmaxx ∈ ST P(X1 = x1, …, XT = xT, O | λ), P* = P(x*, O | λ).
Pre t = 1, …, T a j ∈ S označme δt(j) pravdepodobnosť najlepšej cesty, ktorá v čase t končí v stave j:
δt(j) = maxx1, …, xt−1 ∈ S P(X1 = x1, …, Xt−1 = xt−1, Xt = j, O1, …, Ot | λ).
- Inicializácia: pre každé j ∈ S polož δ1(j) = πj bj(O1).
- Indukcia: pre t = 1, …, T − 1 a každé j ∈ S polož δt+1(j) = maxi ∈ S [δt(i) aij] · bj(Ot+1), ψt+1(j) = argmaxi ∈ S δt(i) aij (ψt+1(j) je najlepší predchodca; pri zhode vyber ktoréhokoľvek).
- Ukončenie: P* = maxj ∈ S δT(j) a x*T = argmaxj ∈ S δT(j).
- Spätný prechod: pre t = T − 1, T − 2, …, 1 polož x*t = ψt+1(x*t+1); po t = 1 vráť x* = (x*1, …, x*T) a P*.
Algoritmus skončí po T − 1 krokoch indukcie a T − 1 krokoch spätného prechodu; čas je opäť O(N2 T). V praxi sa namiesto súčinov sčítavajú logaritmy, aby čísla nepodtiekli.
Rovnaká myšlienka ako dopredný algoritmus, len namiesto súčtu cez všetky cesty sa berie tá najlepšia. Do každého stavu v každom čase vedie jediná „víťazná“ cesta — keby najlepšia celková cesta šla tadiaľ, aj tak by do tohto bodu prišla po nej. Je to dynamické programovanie, príbuzné hľadaniu najkratšej cesty z dielu o prehľadávaní stavového priestoru.
δt+1(j) = maxi δt(i) aij · bj(Ot+1), ψt+1(j) = argmaxi δt(i) aij
- δt(i)
- pravdepodobnosť najlepšej histórie, ktorá v čase t končí kockou i; horšie histórie do i už nepotrebujeme — keby najlepšia celá cesta viedla cez i, pokračovala by po tej najlepšej
- aij
- cena prechodu z i do j; malé aPF = 0,05 je dôvod, prečo sa Viterbimu nechce prepínať kvôli jednej šestke
- maxi, ψt+1(j)
- na rozdiel od dopredného algoritmu nesčítavame, ale vyberáme najlepšieho predchodcu — chceme jednu cestu, nie pravdepodobnosť všetkých; ψ si pamätá, kto vyhral (v mriežke jantárové šípky), aby sa dala cesta na konci spätne zostaviť
- bj(Ot+1)
- ako dobre kocka j vysvetľuje nový hod — rovnako ako pri α
Na dvanástich hodoch je vidieť, ako Viterbi rozhoduje. Prvých šesť hodov (5, 2, 2, 5, 1, 1) vyzerá poctivo. Potom padnú dve šestky za sebou a ďalšie dve o kúsok ďalej — a najlepšia cesta prepne na falošnú kocku. V skutočnosti krupiér vymenil kocku až o štyri hody neskôr; dve šestky za sebou padajú aj poctivej kocke.
Príklad — Viterbi krok za krokom na hodoch 1, 6, 3
Štart je rovnaký ako pri α: δ1(P) = 0,0833, δ1(F) = 0,0500. Pre šestku v druhom hode:
δ2(P) = max(0,0833 · 0,95; 0,0500 · 0,1) · 1/6 = 0,0792 · 1/6 = 0,0132 (vyhral P),
δ2(F) = max(0,0833 · 0,05; 0,0500 · 0,9) · 0,5 = 0,0450 · 0,5 = 0,0225 (vyhral F)
(farby podľa vzorca vyššie).
| t | hod | δt(P) | ψt(P) | δt(F) | ψt(F) |
|---|---|---|---|---|---|
| 1 | 1 | 0,083333 | — | 0,050000 | — |
| 2 | 6 | 0,013194 | P | 0,022500 | F |
| 3 | 3 | 0,002089 | P | 0,002025 | F |
Na konci vyhrá P (0,002089 > 0,002025) a spätne po odkazoch ψ vyjde cesta PPP — presne história z prvého príkladu, ktorá bola zo všetkých ôsmich najpravdepodobnejšia. Dopredný algoritmus však pre tretí hod dáva P(F | O1, O2, O3) = α3(F)/α3(P) + α3(F) = 0,002283/0,004913 = 0,465. Najlepšia cesta a najpravdepodobnejší stav sa tu zhodujú (P), ale „víťazstvo“ je tesné a tri hody na istotu nestačia. Vo všeobecnosti sa zhodovať nemusia — k tomu sa vrátime pri aposteriórnom dekódovaní.
import numpy as np
def viterbi(hody, pi, A, B):
T, N = len(hody), len(pi)
delta = np.log(pi) + np.log(B[:, hody[0]])
odkud = np.zeros((T, N), dtype=int)
for t in range(1, T):
kandidati = delta[:, None] + np.log(A) # z každého i do každého j
odkud[t] = kandidati.argmax(axis=0)
delta = kandidati.max(axis=0) + np.log(B[:, hody[t]])
cesta = [int(delta.argmax())]
for t in range(T - 1, 0, -1): # späť po víťazných odkazoch
cesta.append(odkud[t][cesta[-1]])
return cesta[::-1]
5. Všetkých 300 hodov
Falošná kocka bola v hre 88-krát, v deviatich úsekoch. Viterbi označil za falošné 62 hodov, z toho 56 správne, a celkovo určil kocku správne pri 87,3 % hodov. Dlhé úseky podvodu našiel, krátke však prehliadol alebo zlial dohromady — namiesto deviatich úsekov vidí dva. Na krátkom úseku jednoducho nepadne dosť šestiek, aby to stálo za „drahú“ výmenu kocky (pravdepodobnosť výmeny je len 0,05).
Definícia — aposteriórna pravdepodobnosť stavu
Nech λ = (π, A, B) je skrytý Markovov model so stavmi S = {1, …, N} a O = (O1, …, OT) pozorovanie s P(O | λ) > 0. Aposteriórna pravdepodobnosť stavu i ∈ S v čase t ∈ {1, …, T} je
γt(i) = P(Xt = i | O1, …, OT, λ).
Na jej výpočet slúžia spätné premenné (pre t < T a P(Xt = i) > 0)
βt(i) = P(Ot+1, …, OT | Xt = i, λ), βT(i) = 1.
Dopredno-spätný algoritmus vypočíta αt(i) dopredným algoritmom, βt(i) odzadu (pre t = T − 1, …, 1) a z oboch γt(i) podľa vzorcov nižšie. Slovami: γt(i) je pravdepodobnosť, že v čase t bol model v stave i, keď poznáme celý pozorovaný rad — minulosť aj budúcnosť.
Viterbi dá jednu odpoveď „bola to táto kocka“. Aposteriórna pravdepodobnosť povie, ako veľmi si sme istí — pre každý hod zvlášť, s ohľadom na všetko, čo padlo predtým aj potom. Spodná krivka v obrázku: kde vystúpi nad polovicu, skôr sa podvádza.
γt(i) = αt(i) · βt(i)/P(O | λ), βt(i) = ∑j aij bj(Ot+1) βt+1(j), βT(i) = 1
- γt(i)
- pravdepodobnosť, že v čase t bola v hre kocka i, keď poznáme všetky hody — pre falošnú kocku je to červená krivka v obrázku
- αt(i)
- dôkazy z minulosti: hody 1 až t a stav i v čase t
- βt(i)
- dôkazy z budúcnosti: ako dobre stav i vysvetľuje hody t + 1 až T. Počíta sa odzadu rovnakým trikom ako α — jeden krok reťazca, emisia, zvyšok budúcnosti. Násobiť α a β smieme, pretože pri známom stave Xt sú minulé a budúce hody nezávislé
- P(O | λ)
- súčin α·β je združená pravdepodobnosť P(Xt = i, O); delením pravdepodobnosťou všetkých hodov z nej urobíme podmienenú. Je to to isté číslo, ktoré dal dopredný algoritmus, a platí ∑i αt(i) βt(i) = P(O | λ) v každom t
Príklad — druhý hod: čo pridá budúcnosť
Zostaňme pri hodoch 1, 6, 3 a pýtajme sa na druhý hod (šestku). Spätný krok od β3 = 1 s tretím hodom (trojkou):
β2(P) = 0,95 · 1/6 + 0,05 · 0,1 = 0,1633, β2(F) = 0,1 · 1/6 + 0,9 · 0,1 = 0,1067.
(V každom súčine je prvý činiteľ prechod aij, druhý emisia trojky bj(3) a β3(j) = 1 sa nepíše.) Podľa vzorca vyššie (farby zodpovedajú jeho členom):
γ2(F) = 0,024583 · 0,106667/0,004913 = 0,534.
Keby sme poznali len prvé dva hody, bolo by P(F | O1, O2) = α2(F)/α2(P) + α2(F) = 0,637. Trojka, ktorá padla potom, je na falošnej kocke menej pravdepodobná, a tak podozrenie na druhý hod spätne zníži na 0,534.
Definícia — aposteriórne dekódovanie a presnosť
Nech λ je skrytý Markovov model so stavmi S, O = (O1, …, OT) pozorovanie a γt(i) aposteriórne pravdepodobnosti stavov z predchádzajúcej definície. Aposteriórne dekódovanie je postupnosť x̂ = (x̂1, …, x̂T) ∈ ST, kde
x̂t = argmaxi ∈ S γt(i) pre každé t = 1, …, T
(stav sa volí v každom čase zvlášť). Nech ďalej x ∈ ST je skutočná postupnosť stavov a y ∈ ST ľubovoľné dekódovanie (aposteriórne alebo Viterbiho). Presnosť dekódovania y je podiel časov, v ktorých sa zhoduje so skutočnosťou:
presnosť(y, x) = |{t ∈ {1, …, T} : yt = xt}|/T ∈ [0, 1].
Aposteriórne dekódovanie maximalizuje očakávaný počet správne určených hodov, Viterbi pravdepodobnosť, že je správna celá cesta naraz. Preto môže aposteriórna postupnosť obsahovať aj prechod, ktorý má v modeli pravdepodobnosť nula — pri kasíne taký nie je, ale vo všeobecnosti to nastať môže.
Keby sme pri každom hode vybrali kocku s väčšou aposteriórnou pravdepodobnosťou, trafili by sme 87,7 % — o chlp viac než Viterbi (263 hodov z 300 oproti 262, rozdiel jediného hodu). (Viterbi hľadá najlepšiu celú cestu, aposteriórne dekódovanie najlepší odhad každého hodu zvlášť; to nie je to isté.) A pozor na jednu simuláciu: v dvanástich rôznych pokusoch sa presnosť Viterbiho algoritmu pohybovala od 73,3 do 90,0 %, v priemere 83,4 %. Podľa toho, aké dlhé úseky podvodu náhoda vyrobí.
6. Učenie: Baumov–Welchov algoritmus
Zatiaľ sme parametre kasína poznali. Čo ak vieme len to, že kocky sú dve, a všetko ostatné treba vyčítať z hodov?
Algoritmus — Baumov–Welchov algoritmus
Je to algoritmus EM (Baum a kol., okolo roku 1970).
Vstup: počet skrytých stavov N ≥ 1, množina symbolov V, pozorovanie O = (O1, …, OT) ∈ VT s T ≥ 2, počiatočný odhad parametrov λ(0) = (π, A, B) s P(O | λ(0)) > 0 a počet iterácií K ≥ 1 (alebo tolerancia ε > 0).
Výstup: parametre λ(K) s vierohodnosťou P(O | λ(K)) ≥ P(O | λ(0)).
Pre k = 0, 1, …, K − 1 opakuj s parametrami λ(k):
- Krok E: dopredno-spätným algoritmom vypočítaj αt(i), βt(i), P(O | λ(k)), aposteriórne pravdepodobnosti γt(i) pre t = 1, …, T a pravdepodobnosti prechodov ξt(i, j) = P(Xt = i, Xt+1 = j | O, λ(k)), t = 1, …, T − 1, i, j ∈ S.
- Krok M: nové parametre λ(k+1) sú pre všetky i, j ∈ S a o ∈ V πi = γ1(i), aij = ∑t=1T−1 ξt(i, j)/∑t=1T−1 γt(i), bi(o) = ∑t : Ot = o γt(i)/∑t=1T γt(i).
- Zastavenie: skonči po K iteráciách, prípadne skôr, keď log P(O | λ(k+1)) − log P(O | λ(k)) < ε.
Platí P(O | λ(k+1)) ≥ P(O | λ(k)) — vierohodnosť v žiadnej iterácii neklesne. Algoritmus konverguje k stacionárnemu bodu vierohodnosti, v praxi obvykle k lokálnemu maximu, ktoré nemusí byť globálne; výsledok preto závisí od počiatočného odhadu.
Keby sme vedeli, kedy bola v hre ktorá kocka, vypočítali by sme parametre prostým počítaním. Nevieme to — ale s nejakým odhadom parametrov vieme vypočítať, s akou pravdepodobnosťou bola ktorá kocka kde. Spočítame teda „mäkké“ počty, z nich lepšie parametre, z nich lepšie počty… Každé kolo model zlepší.
Očakávaný počet prechodov sa vypočíta z rovnakých α a β ako γ, len sa medzi ne vloží jeden krok reťazca:
ξt(i, j) = αt(i) aij bj(Ot+1) βt+1(j)/P(O | λ)
- αt(i)
- hody do času t a kocka i v čase t — ľavý koniec prechodu
- aij
- samotný prechod i → j, ktorého početnosť odhadujeme
- bj(Ot+1)
- hod t + 1 musí vygenerovať nová kocka j
- βt+1(j)
- zvyšok hodov od t + 2 ďalej, vysvetlený z kocky j — pravý koniec prechodu
- P(O | λ)
- delením zo združenej pravdepodobnosti „prechod a všetky hody“ urobíme podmienenú „prechod, keď poznáme hody“
âij = ∑t=1T−1 ξt(i, j)/∑t=1T−1 γt(i)
- âij
- nový odhad pravdepodobnosti prechodu — relatívna početnosť, ako keby sme počítali čiarky
- ∑ ξt(i, j)
- očakávaný počet prechodov i → j; namiesto „prešlo sa, alebo nie“ (1 alebo 0) sčítavame pravdepodobnosti, pretože stavy nevidíme
- ∑ γt(i)
- očakávaný počet odchodov zo stavu i; sčítava sa len do T − 1, pretože z posledného stavu už žiadny prechod nevedie. Vďaka tomu sa riadok novej matice sčíta na 1
opakuj (u nás 100-krát):
α, β, P(O) ← dopredno-spätný algoritmus s aktuálnymi π, A, B
# krok E: mäkké počty
pre každé t, i: γ[t][i] ← α[t][i] · β[t][i] / P(O)
pre každé t < T, i, j: ξ[t][i][j] ← α[t][i] · a[i][j] · b[j](O[t+1]) · β[t+1][j] / P(O)
# krok M: relatívne početnosti
π[i] ← γ[1][i]
a[i][j] ← ∑_{t<T} ξ[t][i][j] / ∑_{t<T} γ[t][i]
b[i](o) ← ∑_{t: O[t]=o} γ[t][i] / ∑_t γ[t][i]
Začali sme od zlého odhadu: kocky sa skoro nelíšia a vymieňajú sa často. Z 300 hodov sa Baum–Welch dostal k modelu, ktorý kocky nevymieňa takmer vôbec a falošnej kocke dáva šestku len s pravdepodobnosťou 0,39 — na spoľahlivý odhad je 300 hodov málo. Z 3 000 hodov (iná simulácia toho istého kasína) už vyšiel veľmi blízko pravde:
| Parameter | Skutočnosť | Odhad z 3 000 hodov |
|---|---|---|
| poctivá → falošná | 0,05 | 0,039 |
| falošná → poctivá | 0,10 | 0,090 |
| šestka na falošnej kocke | 0,50 | 0,491 |
| šestka na poctivej kocke | 0,167 | 0,163 |
Prečo 300 hodov nestačí, ukazuje vierohodnosť. Počas 100 iterácií na našich 300 hodoch vzrástla z 10−231,26 na 10−227,14 — a to je viac než 10−230,03 skutočného modelu kasína. Naučený model teda vysvetľuje práve tieto hody lepšie než pravda: prispôsobil sa aj náhodným výkyvom konkrétnych dát. Odhad maximálnej vierohodnosti sa k pravde blíži až s pribúdajúcimi dátami.
7. Skryté Markovove modely v praxi
- Rozpoznávanie reči. Od osemdesiatych rokov do nástupu hlbokých sietí okolo roku 2010 stáli takmer všetky systémy na HMM: skryté stavy sú časti hlások, pozorovania krátke úseky zvukového spektra a Viterbi hľadá najpravdepodobnejšiu postupnosť slov.
- Jazyk. Určovanie slovných druhov: skrytý stav je slovný druh, pozorovanie slovo. „Rada“ môže byť podstatné meno (dobrá rada) aj prídavné meno (som rada) — rozhodne kontext.
- Bioinformatika. Hľadanie génov v DNA (kódujúce a nekódujúce úseky sú skryté stavy) alebo profilové HMM pre rodiny bielkovín v databáze Pfam.
- Spojité stavy. Keď skrytý stav nie je „kocka A alebo B“, ale poloha a rýchlosť, namiesto HMM sa používa Kalmanov filter — má v osnove vlastný diel.
8. Zhrnutie
- Skrytý Markovov model je Markovov reťazec skrytých stavov, z ktorých vidíme len emisie; určujú ho π, A a B.
- Dopredný algoritmus vypočíta pravdepodobnosť pozorovaní v čase O(N2T) namiesto súčtu cez 2300 ciest; kasíno s podvodom vysvetľuje naše hody asi 2 600-krát lepšie než poctivá hra.
- Viterbiho algoritmus nájde najpravdepodobnejšiu cestu skrytých stavov dynamickým programovaním — v našej simulácii určil kocku správne pri 87,3 % hodov, krátke úseky však prehliadol.
- Dopredno-spätný algoritmus dá aposteriórnu pravdepodobnosť stavu v každom čase.
- Baumov–Welchov algoritmus sa parametre naučí len z pozorovaní — potrebuje však dosť dát: 300 hodov nestačilo, 3 000 áno.
Chcete si to vyskúšať? Nechajte AI agenta naučiť HMM s dvoma stavmi na denných výnosoch akciového indexu — a pozrite sa, či sám nájde „pokojné“ a „rozbúrené“ obdobia trhu.
Máte na to iný názor? Napíšte na support@coden-app.com.