Algoritm înainte-înapoi

De la Wikipedia, enciclopedia liberă.
Salt la navigare Salt la căutare

Algoritmul înainte-înapoi este un algoritm inferențial pentru modelele ascunse de Markov care calculează probabilitatea posterioară marginală a tuturor variabilelor de stare ascunse, având în vedere o succesiune de observații. , adică calculează, pentru toate variabilele de stare ascunse , distributia . Această sarcină inferențială se numește de obicei netezire . Algoritmul folosește principiul de programare dinamică în doi pași pentru a calcula în mod eficient valorile necesare pentru a obține distribuții marginale posterioare. Primul pas merge înainte în timp, în timp ce al doilea merge înapoi; de aici și numele înainte-înapoi , înainte-înapoi, al algoritmului.

Termenul algoritm înainte - înapoi este folosit ca referință la un algoritm aparținând clasei generice de algoritmi care operează pe secvențe de modele într-o manieră alternativă față de parametrul adoptat pentru evoluție, în general timp. În acest sens, restul acestei intrări se referă la algoritmul în forma sa generică și nu la un exemplu particular al acestei clase.

Prezentare generală

Ca prim pas, algoritmul înainte - înapoi calculează un set de probabilități "înainte" care oferă, pentru toți , probabilitatea de a ajunge într-o anumită stare, dată fiind prima observații în secvență, adică . Ca un al doilea pas, algoritmul calculează un set de probabilități „înapoi” care oferă probabilitatea de a observa observațiile rămase date de un anumit punct de plecare. , sau . Aceste două seturi de distribuții de probabilitate pot fi apoi combinate pentru a obține distribuția peste stări într-un anumit moment specific, având în vedere întreaga succesiune de observații:

unde ultimul pas rezultă din aplicarea regulii lui Bayes și din independența condiționată a și de dat .

După cum sa subliniat mai sus, algoritmul implică trei pași:

  1. calculul probabilității „înainte”
  2. calculul probabilității înapoi
  3. calculul valorilor esențiale sau a valorilor uniformizate , adică valori care rezumă tendința principală sau generală a setului de valori sau a unei părți a acestuia.

Pașii înainte și înapoi pot fi, de asemenea, numiți „treceți mesajul înainte” și „mesajul pas înapoi) - acești termeni sunt în general legați de trecerea mesajului utilizat în abordările de propagare a credințelor (propagarea credințelor). La fiecare observație unică în secvență, sunt calculate probabilitățile utilizate pentru calcularea următoarei observații. În timpul pasajului înapoi, se poate efectua și calculul valorilor esențiale ( pas de netezire ). Acest pas permite algoritmului să țină cont de rezultatele anterioare pentru a calcula mai precis altele noi.

Algoritmul înainte - înapoi poate fi folosit pentru a găsi starea cea mai probabilă pentru orice moment din timp. Cu toate acestea, nu poate fi folosit pentru a găsi cea mai probabilă succesiune de stări ( cf. algoritmul lui Viterbi ).

Probabilitate înainte

Următoarea descriere va folosi mai multe matrici de valori de probabilitate decât distribuții de probabilitate, deși, în general, algoritmul înainte-înapoi poate fi aplicat atât modelelor de probabilitate continue, cât și discrete.

Transformăm distribuțiile de probabilitate legate de un model Markov ascuns dat în notație matricială după cum urmează. Probabilitățile de tranziție a unei variabile aleatorii date , reprezentând toate stările posibile în modelul ascuns Markov, va fi reprezentat de matrice unde indexul rândului, i, va reprezenta starea de pornire și indexul coloanei, j, starea de sosire. Exemplul de mai jos reprezintă un sistem în care probabilitatea de a rămâne în aceeași stare după fiecare pas este de 70% și cea de tranziție la o altă stare este de 30%. Matricea de tranziție este:

Într-un model tipic Markov am înmulți un vector de stare cu matricea de mai sus pentru a obține probabilitățile pentru stările ulterioare. Într-un model ascuns Markov starea este necunoscută și ceea ce observăm sunt evenimente asociate cu stări posibile. O matrice de evenimente a formei:

oferă probabilitățile de observare a evenimentelor pornind de la o anumită stare. În exemplul anterior, evenimentul 1 va fi observat 90% din timp dacă pornim de la starea 1 în timp ce evenimentul 2 are o probabilitate de 10% să apară întotdeauna începând de la starea 1. Dimpotrivă, evenimentul 1 va fi observat doar 20% din timpul dacă pornim de la starea 2 și evenimentul 2 are o șansă de 80% să apară. Având un vector de stare ( ), probabilitatea de a observa evenimentul j este atunci:

Aceasta poate fi reprezentată sub formă de matrice prin multiplicarea vectorului de stare ( ) pentru matricea de observare ( ) conținând doar elemente de-a lungul diagonalei. Fiecare element este probabilitatea evenimentului observat dat de fiecare stare. Continuând exemplul anterior, o observație a evenimentului 1 ar fi:

Aceasta permite calcularea probabilităților asociate cu trecerea la o nouă stare și observarea unui eveniment dat ca:

Vectorul de probabilitate rezultat conține elemente care indică probabilitatea de tranziție la fiecare stare, adică observarea unui eveniment dat. Acest proces poate fi urmărit în continuare cu observații suplimentare utilizând:

Această valoare este vectorul de probabilitate directă. Componenta sa i-a asigură:

De obicei, vectorul de probabilitate nu rămâne normalizat la fiecare pas, astfel încât componentele sale se adaugă la 1. Un factor de scală este, prin urmare, introdus la fiecare pas, astfel încât:

unde este reprezintă vectorul scalat de la pasul anterior e reprezintă factorul de scală datorită căruia componentele vectorului rezultat se adună la 1. Produsul factorilor de scală este probabilitatea totală de a observa evenimentele date indiferent de stările finale:

Acest lucru ne permite să interpretăm vectorul de probabilitate scalat ca:

Prin urmare, constatăm că produsul factorilor de scară ne oferă probabilitatea totală de a observa o secvență dată până la timpul t și că vectorul de probabilitate scalat ne oferă probabilitatea de a fi în fiecare stare în acel moment.

Probabilitate înapoi

O procedură similară poate fi construită pentru a găsi probabilități înapoi. Acestea oferă probabilitățile:

Aceasta înseamnă că, presupunând că plecăm într-o anumită stare ( ), acum suntem interesați de probabilitatea de a observa toate evenimentele viitoare din această stare. Deoarece starea inițială este luată ca dată (adică probabilitatea a priori a acestei stări este egală cu 100%), începem cu:

Observați că acum folosim un vector coloană, în timp ce probabilitățile de avansare profită de vectorii rând. Apoi putem lucra înapoi folosind:

Deși am putea normaliza acest vector astfel încât componentele sale să adauge 1, acest lucru nu se face de obicei. Observând că fiecare componentă conține probabilitatea succesiunii evenimentelor viitoare, având în vedere o anumită stare inițială, normalizarea acestui vector ar fi echivalentă cu aplicarea teoremei lui Bayes pentru a găsi probabilitatea fiecărei stări inițiale date evenimentelor viitoare (presupunând distribuții uniforme a priori pentru vector de stare finală). Cu toate acestea, este mai frecvent să scalați acest vector folosind aceleași constante utilizat în calculele probabilității directe. nu este scalat, dar operațiile ulterioare utilizează:

unde este reprezintă vectorul scalat anterior. Acest rezultat înseamnă că vectorul de probabilitate a fost scalat și asociat cu probabilitățile înapoi prin:

Acest lucru este util deoarece ne permite să găsim probabilitatea totală de a fi în fiecare stare la un anumit moment, t, prin înmulțirea cu aceste valori:

Pentru a înțelege acest lucru, observăm că oferă probabilitatea de a observa evenimentele date într-un mod care trece prin stat la ora t. Această probabilitate include probabilitățile directe care acoperă toate evenimentele până la momentul t, precum și probabilitățile înapoi care includ toate evenimentele viitoare. Acesta este numeratorul pe care l-am căutat pentru ecuația noastră și îl împărțim la probabilitatea totală a secvenței de observații pentru a o normaliza și a extrage doar probabilitatea pentru care . Aceste valori sunt uneori numite „ valori netezite” deoarece combină probabilitățile înainte și înapoi pentru a calcula o probabilitate finală.

Valori prin urmare ele oferă probabilitatea de a fi în orice stare la momentul t. Ca atare, acestea sunt utile pentru a determina starea cea mai probabilă în orice moment al timpului. Trebuie menționat, totuși, că termenul „starea cea mai probabilă” este oarecum ambiguu. În timp ce starea cea mai probabilă este cea mai favorabilă pentru a fi cea corectă la un moment dat, succesiunea stărilor individuale probabile nu este neapărat cea mai probabilă succesiune. Acest lucru se datorează faptului că probabilitățile pentru fiecare punct sunt calculate independent una de cealaltă. Acestea nu iau în considerare probabilitățile de tranziție între stări și, prin urmare, este posibil să se obțină stări în două timpi (t și t + 1), care sunt ambele mai probabile în acele instanțe, dar care au o probabilitate foarte mică de a se produce împreună, că este . Cea mai probabilă succesiune de stări care produce o succesiune de observații poate fi găsită folosind algoritmul Viterbi .

Exemplu

Acest exemplu ia lumea umbrelelor ca referință în Russel & Norvig 2003 pp. 540 în care am dori să deducem condițiile atmosferice având în vedere observația unui om care poartă o umbrelă sau nu. Presupunem două stări posibile pentru condițiile atmosferice: starea 1 = ploaie, starea 2 = fără ploaie. Să presupunem că condițiile atmosferice au o șansă de 70% să rămână la fel în fiecare zi și o șansă de 30% să se schimbe. Probabilitățile de tranziție sunt apoi:

De asemenea, presupunem că fiecare dintre cele două stări ale condițiilor atmosferice generează două evenimente: eveniment 1 = umbrelă, eveniment 2 = fără umbrelă. Probabilitățile condiționate ca aceste evenimente să apară în fiecare dintre stări sunt date de matricea probabilității:

Să presupunem că observăm următoarea succesiune de evenimente: {umbrelă, umbrelă, fără umbrelă, umbrelă, umbrelă}. Acest lucru va fi reprezentat în calculele noastre ca:

Observați că elementul diferă de ceilalți datorită observației „fără umbrelă”.

Pentru a calcula probabilitățile directe, începem cu:

care este vectorul nostru de stare a priori care indică faptul că nu cunoaștem starea condițiilor atmosferice înainte de observațiile noastre. În timp ce vectorul de stare ar trebui dat ca vector de rând, vom folosi transpunerea matricei în așa fel încât următoarele calcule să fie mai lizibile. Calculele noastre sunt apoi scrise sub forma:

in loc de

Rețineți că și matricea de transformare este transpusă, dar în exemplul nostru transpunerea este egală cu matricea originală. Prin efectuarea acestor calcule și normalizarea rezultatelor obținem:

Pentru probabilitățile înapoi, începem cu:

Prin urmare, putem calcula (folosind observațiile în ordine inversă și normalizând cu constante diferite):

În cele din urmă, vom calcula valorile de probabilitate netezite . Acest rezultat trebuie, de asemenea, să fie scalat în așa fel încât componentele sale să se adauge la 1. Acest lucru se datorează faptului că nu scalăm probabilitățile înapoi cu găsit anterior. Astfel, vectorii de probabilitate înapoi anteriori reprezintă, de fapt, probabilitatea fiecărei stări în momentul în care s-au dat observații viitoare. Deoarece acești vectori sunt proporționali cu probabilitățile reale înapoi, rezultatul trebuie redimensionat din nou.

Si noti che il valore di è uguale a e che è uguale a . Naturalmente questo consegue perché sia che iniziano con distribuzioni a priori uniformi sopra i vettori di stato iniziale e finale rispettivamente e tengono d'acconto di tutte le osservazioni. Tuttavia, sarà solo uguale a quando il nostro vettore di stato iniziale rappresenta una distribuzione a priori uniforme (cioè una con tutti gli elementi identici tra loro). Quando questo non è il caso, è necessario combinare con il vettore di stato iniziale per trovare lo stato iniziale più probabile. Perciò scopriamo che le probabilità in avanti per sé stesse sono sufficienti per calcolare lo stato finale più probabile. Analogamente, le probabilità all'indietro possono essere combinate con il vettore di stato iniziale per fornire lo stato iniziale più probabile date le osservazioni. Le probabilità in avanti e all'indietro richiedono solo di essere combinate per poter inferire gli stati più probabili tra i punti iniziale e finale.

I calcoli sopra rivelano che lo stato delle condizioni atmosferiche più probabile per ogni giorno, eccetto che per il terzo, è "pioggia". Inoltre ci dicono di più, in quanto tali calcoli ora ci forniscono un modo per quantificare le probabilità di ogni stato ad istanti differenti. Maggiormente importante, il nostro valore a quantifica la nostra conoscenza del vettore di stato alla fine della successione di osservazioni. Possiamo usarlo infatti per predire la probabilità dei vari stati delle condizioni atmosferiche di domani così come la probabilità di osservare un ombrello.

Prestazioni

La procedura più diretta per la soluzione di questo problema è la generazione di tutte le possibili successioni di stati e il calcolo della probabilità congiunta di ogni successione di stati con la serie osservata di eventi. Questo approccio ha complessità temporale , dove è la lunghezza delle successioni e è il numero di simboli nell'alfabeto dello stato. Operando in questo modo i problemi reali diventano intrattabili in quanto il numero di possibili successioni di nodi nascosti tipicamente è estremamente elevato. Tuttavia, l'algoritmo di forward–backward ha complessità temporale .

Sono noti vari miglioramenti dell'algoritmo di forward–backward che permettono al calcolo di collocarsi in uno spazio costante. Inoltre, nel tempo sono stati sviluppati algoritmi per calcolare efficientemente tramite uno smoothing in linea ( online smoothing ) dei dati come l'algoritmo FLS ( fixed-lag smoothing ) Russel & Norvig 2003 pp. 552 .

Pseudo-codice

 ForwardBackward(guessState, sequenceIndex):
    if sequenceIndex is past the end of the sequence, return 1
    if (guessState, sequenceIndex) has been seen before, return saved result
    result = 0
    for each neighboring state n:
        result = result + (transition probability from guessState to n given observation element at sequenceIndex)
                        * ForwardBackward(n, sequenceIndex+1)
    save result for (guessState, sequenceIndex)
    return result

Esempio in Python

Dato il modello di Markov nascosto (come nell' algoritmo di Viterbi ) qui rappresentato nel linguaggio di programmazione Python :

 states = ( 'Healthy' , 'Fever' )
end_state = 'E'
 
observations = ( 'normal' , 'cold' , 'dizzy' )
 
start_probability = { 'Healthy' : 0.6 , 'Fever' : 0.4 }
 
transition_probability = {
   'Healthy' : { 'Healthy' : 0.69 , 'Fever' : 0.3 , 'E' : 0.01 },
   'Fever' : { 'Healthy' : 0.4 , 'Fever' : 0.59 , 'E' : 0.01 },
   }
 
emission_probability = {
   'Healthy' : { 'normal' : 0.5 , 'cold' : 0.4 , 'dizzy' : 0.1 },
   'Fever' : { 'normal' : 0.1 , 'cold' : 0.3 , 'dizzy' : 0.6 },
   }

Possiamo scriverne un'implementazione tipo questa:

 def fwd_bkw ( x , states , a_0 , a , e , end_st ):
    L = len ( x )

    fwd = []
    # Run forward
    for i , x_i in enumerate ( x ):
        f_curr = {}
        for st in states :
            if i == 0 :
                # Initialize base fwd cases
                prev_f_sum = a_0 [ st ]
            else :
                prev_f_sum = sum ( f_prev [ k ] * a [ k ][ st ] for k in states )

            f_curr [ st ] = e [ st ][ x_i ] * prev_f_sum

        fwd . append ( f_curr )
        f_prev = f_curr

    p_fwd = sum ( f_curr [ k ] * a [ k ][ end_st ] for k in states )

    bkw = []
    # Run bkw
    for i , x_i_plus in enumerate ( reversed ( x [ 1 :] + ( None ,))):
        b_curr = {}
        for st in states :
            if i == 0 :
                # Initialize base bkw cases
                b_curr [ st ] = a [ st ][ end_st ]
            else :
                b_curr [ st ] = sum ( a [ st ][ l ] * e [ l ][ x_i_plus ] * b_prev [ l ] for l in states )

        bkw . insert ( 0 , b_curr )
        b_prev = b_curr

    p_bkw = sum ( a_0 [ l ] * e [ l ][ x [ 0 ]] * b_curr [ l ] for l in states )

    posterior = {}
    for st in states :
        posterior [ st ] = [ fwd [ i ][ st ] * bkw [ i ][ st ] / p_fwd for i in xrange ( L )]

    assert p_fwd == p_bkw
    return fwd , bkw , posterior

La funzione fwd_bkw ammette i seguenti argomenti: x è la successione di osservazioni, ad esempio ['normal', 'cold', 'dizzy'] ; states è l'insieme degli stati nascosti; a_0 è la probabilità iniziale; a sono le probabilità di transizione; ed e sono le probabilità di emissione ossia di finire un certo stato.

Per mantenere semplice il codice, assumiamo che la successione di osservazioni x sia non vuota e che le componenti a[i][j] ed e[i][j] siano definite per tutti gli stati i,j .

Nell'esempio l'algoritmo forward-backward è impiegato come segue:

 def example ():
    return fwd_bkw ( observations ,
                   states ,
                   start_probability ,
                   transition_probability ,
                   emission_probability ,
                   end_state )
for line in example ():
    print ' ' . join ( map ( str , line ))

Bibliografia

Voci correlate

Collegamenti esterni

Statistica Portale Statistica : accedi alle voci di Wikipedia che trattano di statistica