Algorytm forward – backward - Forward–backward algorithm

Algorytm przód-tył jest wnioskowanie algorytm dla ukrytych modeli Markowa , który oblicza tylne marginesowymi wszystkich ukrytych zmiennych stanu danej sekwencji obserwacji / emisji , czyli oblicza, dla wszystkich ukrytych zmiennych stanu , dystrybucji . To zadanie wnioskowania jest zwykle nazywane wygładzaniem . Algorytm wykorzystuje zasadę programowania dynamicznego do wydajnego obliczania wartości wymaganych do uzyskania późniejszych rozkładów krańcowych w dwóch przejściach. Pierwszy przebieg idzie do przodu w czasie, podczas gdy drugi cofa się w czasie; stąd nazwa algorytm naprzód – wstecz .

Termin algorytm naprzód – wstecz jest również używany w odniesieniu do dowolnego algorytmu należącego do ogólnej klasy algorytmów, które działają na modelach sekwencji w sposób „przód – tył”. W tym sensie opisy w pozostałej części tego artykułu odnoszą się tylko do jednego konkretnego przypadku tej klasy.

Przegląd

W pierwszym przebiegu algorytm forward – backward oblicza zbiór prawdopodobieństw „forward”, które zapewniają wszystkim prawdopodobieństwo znalezienia się w jakimkolwiek określonym stanie, biorąc pod uwagę pierwsze obserwacje w sekwencji, tj . W drugim przebiegu algorytm oblicza zbiór prawdopodobieństw wstecznych, które zapewniają prawdopodobieństwo obserwacji pozostałych obserwacji w dowolnym punkcie początkowym , tj . Te dwa zestawy rozkładów prawdopodobieństwa można następnie połączyć, aby uzyskać rozkład na stanach w dowolnym określonym momencie, biorąc pod uwagę całą sekwencję obserwacji:

Ostatnim krokiem wynika z zastosowania reguły Bayesa i warunkowej niezależności od i podane .

Jak opisano powyżej, algorytm obejmuje trzy kroki:

  1. obliczanie prawdopodobieństw wyprzedzających
  2. obliczanie prawdopodobieństw wstecz
  3. obliczanie wygładzonych wartości.

Kroki do przodu i do tyłu mogą być również nazywane „przekazywaniem wiadomości do przodu” i „przekazywaniem wiadomości do tyłu” - terminy te wynikają z przekazywania wiadomości stosowanego w podejściach do propagacji ogólnych przekonań . Przy każdej pojedynczej obserwacji w sekwencji obliczane są prawdopodobieństwa, które mają być użyte do obliczeń przy następnej obserwacji. Krok wygładzania można obliczyć jednocześnie podczas przejścia wstecz. Ten krok umożliwia algorytmowi uwzględnienie wszelkich wcześniejszych obserwacji danych wyjściowych w celu obliczenia dokładniejszych wyników.

Algorytm naprzód – wstecz może być użyty do znalezienia najbardziej prawdopodobnego stanu w dowolnym momencie. Nie można go jednak użyć do znalezienia najbardziej prawdopodobnej sekwencji stanów (patrz algorytm Viterbiego ).

Prawdopodobieństwa w przód

Poniższy opis będzie używał macierzy wartości prawdopodobieństwa, a nie rozkładów prawdopodobieństwa, chociaż ogólnie algorytm naprzód-wstecz może być stosowany zarówno do ciągłych, jak i dyskretnych modeli prawdopodobieństwa.

Przekształcamy rozkłady prawdopodobieństwa związane z danym ukrytym modelem Markowa na notację macierzową w następujący sposób. Prawdopodobieństwa przejścia danej zmiennej losowej reprezentującej wszystkie możliwe stany w ukrytym modelu Markowa będą reprezentowane przez macierz, w której indeks kolumny będzie reprezentował stan docelowy, a indeks wiersza reprezentował stan początkowy. Przejście od stanu wiersz-wektor do przyrostowego stanu wektor-wiersz jest zapisywane jako . Poniższy przykład przedstawia system, w którym prawdopodobieństwo pozostania w tym samym stanie po każdym kroku wynosi 70%, a prawdopodobieństwo przejścia do innego stanu wynosi 30%. Macierz przejść jest zatem:

W typowym modelu Markowa pomnożymy wektor stanu przez tę macierz, aby otrzymać prawdopodobieństwa dla kolejnego stanu. W ukrytym modelu Markowa stan jest nieznany, a zamiast tego obserwujemy zdarzenia związane z możliwymi stanami. Matryca zdarzeń w postaci:

podaje prawdopodobieństwa obserwacji zdarzeń w określonym stanie. W powyższym przykładzie zdarzenie 1 będzie obserwowane w 90% przypadków, jeśli będziemy w stanie 1, podczas gdy zdarzenie 2 ma 10% prawdopodobieństwo wystąpienia w tym stanie. Natomiast zdarzenie 1 będzie obserwowane tylko w 20% przypadków, jeśli będziemy w stanie 2, a prawdopodobieństwo wystąpienia zdarzenia 2 wynosi 80%. Biorąc pod uwagę dowolny wektor wierszowy opisujący stan układu ( ), prawdopodobieństwo zaobserwowania zdarzenia j wynosi wtedy:

Prawdopodobieństwo danego stanu prowadzącego do obserwowanego zdarzenia j można przedstawić w postaci macierzy, mnożąc wiersz-wektor stanu ( ) przez macierz obserwacji ( ) zawierającą tylko wpisy po przekątnej. Kontynuując powyższy przykład, macierz obserwacji dla zdarzenia 1 wyglądałaby następująco:

To pozwala nam obliczyć nowy nieznormalizowany wektor stanu prawdopodobieństwa za pomocą reguły Bayesa, ważąc według prawdopodobieństwa, że ​​każdy element wygenerowanego zdarzenia 1 jako:

Możemy teraz uczynić tę ogólną procedurę specyficzną dla naszej serii obserwacji. Zakładając wektor stanu początkowego (który można zoptymalizować jako parametr poprzez powtórzenia procedury forward-back), zaczynamy od , następnie aktualizujemy rozkład stanu i ważenie według prawdopodobieństwa pierwszej obserwacji:

Proces ten można przeprowadzić z dodatkowymi obserwacjami przy użyciu:

Ta wartość jest przednim nieznormalizowanym wektorem prawdopodobieństwa. I-ta pozycja tego wektora zapewnia:

Zwykle normalizujemy wektor prawdopodobieństwa na każdym kroku, tak aby jego wpisy sumowały się do 1. W ten sposób na każdym kroku wprowadzany jest współczynnik skalowania, który:

gdzie reprezentuje skalowany wektor z poprzedniego kroku i reprezentuje współczynnik skalujący, który powoduje sumowanie wpisów wynikowego wektora do 1. Iloczyn współczynników skalowania jest całkowitym prawdopodobieństwem zaobserwowania danych zdarzeń niezależnie od stanów końcowych:

To pozwala nam zinterpretować skalowany wektor prawdopodobieństwa jako:

W ten sposób stwierdzamy, że iloczyn współczynników skalowania daje nam całkowite prawdopodobieństwo zaobserwowania danej sekwencji do czasu t, a skalowany wektor prawdopodobieństwa daje nam prawdopodobieństwo przebywania w każdym stanie w tym czasie.

Prawdopodobieństwa wsteczne

Podobną procedurę można skonstruować w celu znalezienia prawdopodobieństw wstecz. Mają one na celu zapewnienie prawdopodobieństw:

Oznacza to, że chcemy teraz założyć, że zaczynamy w określonym stanie ( ), a teraz interesuje nas prawdopodobieństwo zaobserwowania wszystkich przyszłych wydarzeń z tego stanu. Ponieważ przyjmuje się, że stan początkowy jest zadany (tj. Wcześniejsze prawdopodobieństwo tego stanu = 100%), zaczynamy od:

Zauważ, że używamy teraz wektora kolumnowego, podczas gdy prawdopodobieństwa do przodu używają wektorów wierszowych. Następnie możemy pracować wstecz, używając:

Chociaż moglibyśmy również znormalizować ten wektor, aby jego wpisy sumowały się do jednego, zwykle się to nie robi. Zauważając, że każdy wpis zawiera prawdopodobieństwo przyszłej sekwencji zdarzeń przy określonym stanie początkowym, normalizacja tego wektora byłaby równoważna zastosowaniu twierdzenia Bayesa w celu znalezienia prawdopodobieństwa każdego stanu początkowego przy danych przyszłych zdarzeniach (przy założeniu jednakowych wyprzedzeń dla wektora stanu końcowego ). Jednak bardziej powszechne jest skalowanie tego wektora przy użyciu tych samych stałych, które są używane w obliczeniach prawdopodobieństwa w przód. nie jest skalowany, ale kolejne operacje wykorzystują:

gdzie reprezentuje poprzedni przeskalowany wektor. Wynik jest taki, że skalowany wektor prawdopodobieństwa jest powiązany z prawdopodobieństwami wstecznymi przez:

Jest to przydatne, ponieważ pozwala nam znaleźć całkowite prawdopodobieństwo przebywania w każdym stanie w danym czasie t, poprzez pomnożenie tych wartości:

Aby to zrozumieć, zauważamy, że zapewnia prawdopodobieństwo zaobserwowania danych zdarzeń w sposób, który przechodzi przez stan w czasie t. To prawdopodobieństwo obejmuje prawdopodobieństwa przyszłe obejmujące wszystkie zdarzenia do czasu t, jak również prawdopodobieństwa wsteczne, które obejmują wszystkie zdarzenia przyszłe. To jest licznik, którego szukamy w naszym równaniu i dzielimy przez całkowite prawdopodobieństwo sekwencji obserwacji, aby znormalizować tę wartość i wyodrębnić tylko prawdopodobieństwo, że . Te wartości są czasami nazywane „wartościami wygładzonymi”, ponieważ łączą prawdopodobieństwa do przodu i do tyłu w celu obliczenia prawdopodobieństwa końcowego.

Wartości zapewniają zatem prawdopodobieństwo znalezienia się w każdym stanie w czasie t. Jako takie, są one przydatne do określenia najbardziej prawdopodobnego stanu w dowolnym momencie. Termin „najbardziej prawdopodobny stan” jest nieco niejednoznaczny. Podczas gdy najbardziej prawdopodobny stan jest najbardziej prawdopodobny w danym momencie, sekwencja indywidualnie prawdopodobnych stanów nie jest prawdopodobnie sekwencją najbardziej prawdopodobną. Dzieje się tak, ponieważ prawdopodobieństwa dla każdego punktu są obliczane niezależnie od siebie. Nie uwzględniają one prawdopodobieństw przejścia między stanami, dzięki czemu można uzyskać stany w dwóch momentach (t i t + 1), które są najbardziej prawdopodobne w tych punktach czasowych, ale które mają bardzo małe prawdopodobieństwo wystąpienia razem, tj. . Najbardziej prawdopodobną sekwencję stanów, które utworzyły sekwencję obserwacyjną, można znaleźć za pomocą algorytmu Viterbiego .

Przykład

W tym przykładzie za podstawę przyjęto parasolowy świat w Russell & Norvig 2010, rozdział 15, s. 567, w którym chcielibyśmy wywnioskować pogodę na podstawie obserwacji innej osoby noszącej lub nie posiadającej parasola. Zakładamy dwa możliwe stany pogody: stan 1 = deszcz, stan 2 = brak deszczu. Zakładamy, że pogoda ma 70% szans na pozostanie bez zmian każdego dnia i 30% na zmianę. Prawdopodobieństwa przejścia są zatem:

Zakładamy również, że każdy stan generuje jedno z dwóch możliwych zdarzeń: zdarzenie 1 = parasol, zdarzenie 2 = brak parasola. Prawdopodobieństwa warunkowe dla tych występujących w każdym stanie są podane przez macierz prawdopodobieństwa:

Następnie obserwujemy następującą sekwencję zdarzeń: {parasol, parasol, brak parasola, parasol, parasol}, które w naszych obliczeniach przedstawimy jako:

Zauważ, że różni się od innych ze względu na obserwację „bez parasola”.

Obliczając prawdopodobieństwa w przód, zaczynamy od:

który jest naszym poprzednim wektorem stanu wskazującym, że nie wiemy, w jakim stanie jest pogoda przed naszymi obserwacjami. Podczas gdy wektor stanu powinien być podany jako wektor wierszowy, użyjemy transpozycji macierzy, aby poniższe obliczenia były łatwiejsze do odczytania. Nasze obliczenia zapisujemy wtedy w postaci:

zamiast:

Zauważ, że macierz transformacji również jest transponowana, ale w naszym przykładzie transpozycja jest równa oryginalnej macierzy. Wykonanie tych obliczeń i normalizacja wyników zapewnia:

Dla prawdopodobieństw wstecznych zaczynamy od:

Następnie jesteśmy w stanie obliczyć (używając obserwacji w odwrotnej kolejności i normalizując z różnymi stałymi):

Na koniec obliczymy wygładzone wartości prawdopodobieństwa. Wyniki te należy również przeskalować tak, aby ich wpisy sumowały się do 1, ponieważ nie skalowaliśmy prawdopodobieństw wstecz z wartościami znalezionymi wcześniej. Powyższe wektory prawdopodobieństwa wstecznego reprezentują zatem w rzeczywistości prawdopodobieństwo wystąpienia każdego stanu w czasie t, biorąc pod uwagę przyszłe obserwacje. Ponieważ te wektory są proporcjonalne do rzeczywistych wstecznych prawdopodobieństw, wynik musi zostać dodatkowo przeskalowany.

Zauważ, że wartość jest równa i to jest równe . Wynika to naturalnie, ponieważ oba i zaczynają się od jednakowych wyprzedzeń względem wektorów stanu początkowego i końcowego (odpowiednio) i uwzględniają wszystkie obserwacje. Jednak będzie równy tylko wtedy, gdy nasz wektor stanu początkowego reprezentuje jednolity poprzedni (tj. Wszystkie wpisy są równe). Jeśli tak nie jest, należy połączyć go z wektorem stanu początkowego, aby znaleźć najbardziej prawdopodobny stan początkowy. W ten sposób stwierdzamy, że same prawdopodobieństwa wyprzedzające są wystarczające do obliczenia najbardziej prawdopodobnego stanu końcowego. Podobnie, prawdopodobieństwa wsteczne można łączyć z wektorem stanu początkowego, aby zapewnić najbardziej prawdopodobny stan początkowy, biorąc pod uwagę obserwacje. Prawdopodobieństwa do przodu i do tyłu muszą być tylko połączone, aby wywnioskować najbardziej prawdopodobne stany między punktem początkowym i końcowym.

Z powyższych obliczeń wynika, że ​​najbardziej prawdopodobnym stanem pogodowym każdego dnia oprócz trzeciego był „deszcz”. Mówią nam jednak więcej niż to, ponieważ zapewniają teraz sposób ilościowego określenia prawdopodobieństw każdego stanu w różnym czasie. Być może co najważniejsze, nasza wartość w kwantyfikacji naszej wiedzy o wektorze stanu na końcu sekwencji obserwacji. Możemy następnie wykorzystać to do przewidzenia prawdopodobieństwa wystąpienia różnych stanów pogodowych w przyszłości, a także prawdopodobieństwa zaobserwowania parasola.

Występ

Algorytm naprzód – wstecz działa ze złożonością czasową w przestrzeni , gdzie jest długością sekwencji czasowej i liczbą symboli w alfabecie stanu. Algorytm może również działać w stałej przestrzeni ze złożonością czasową poprzez przeliczanie wartości na każdym kroku. Dla porównania, procedura brutalnej siły wygenerowałaby wszystkie możliwe sekwencje stanów i obliczyłaby łączne prawdopodobieństwo każdej sekwencji stanów z obserwowanymi seriami zdarzeń, które miałyby złożoność czasową . Brutalna siła jest trudna do rozwiązania w przypadku realistycznych problemów, ponieważ liczba możliwych sekwencji ukrytych węzłów jest zazwyczaj niezwykle wysoka.

Ulepszenie ogólnego algorytmu naprzód-wstecz, zwanego algorytmem wyspowym, zamienia mniejsze zużycie pamięci na dłuższy czas działania, zajmując czas i pamięć. Ponadto możliwe jest odwrócenie modelu procesu w celu uzyskania algorytmu przestrzenno- czasowego, chociaż proces odwrócony może nie istnieć lub być źle uwarunkowany .

Ponadto opracowano algorytmy do wydajnego obliczania dzięki wygładzaniu online, takim jak algorytm wygładzania o stałym opóźnieniu (FLS).

Pseudo kod

algorithm forward_backward is
    input: guessState
           int sequenceIndex
    output: result

    if sequenceIndex is past the end of the sequence then
        return 1
    if (guessState, sequenceIndex) has been seen before then
        return saved result

    result := 0

    for each neighboring state n:
        result := result + (transition probability from guessState to 
                            n given observation element at sequenceIndex)
                            × Backward(n, sequenceIndex + 1)

    save result for (guessState, sequenceIndex)

    return result

Przykład Pythona

Biorąc pod uwagę HMM (podobnie jak w algorytmie Viterbiego ) reprezentowany w języku programowania 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},
   }

Implementację algorytmu forward-backward możemy napisać następująco:

def fwd_bkw(observations, states, start_prob, trans_prob, emm_prob, end_st):
    """Forward–backward algorithm."""
    # Forward part of the algorithm
    fwd = []
    for i, observation_i in enumerate(observations):
        f_curr = {}
        for st in states:
            if i == 0:
                # base case for the forward part
                prev_f_sum = start_prob[st]
            else:
                prev_f_sum = sum(f_prev[k] * trans_prob[k][st] for k in states)

            f_curr[st] = emm_prob[st][observation_i] * prev_f_sum

        fwd.append(f_curr)
        f_prev = f_curr

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

    # Backward part of the algorithm
    bkw = []
    for i, observation_i_plus in enumerate(reversed(observations[1:] + (None,))):
        b_curr = {}
        for st in states:
            if i == 0:
                # base case for backward part
                b_curr[st] = trans_prob[st][end_st]
            else:
                b_curr[st] = sum(trans_prob[st][l] * emm_prob[l][observation_i_plus] * b_prev[l] for l in states)

        bkw.insert(0,b_curr)
        b_prev = b_curr

    p_bkw = sum(start_prob[l] * emm_prob[l][observations[0]] * b_curr[l] for l in states)

    # Merging the two parts
    posterior = []
    for i in range(len(observations)):
        posterior.append({st: fwd[i][st] * bkw[i][st] / p_fwd for st in states})

    assert p_fwd == p_bkw
    return fwd, bkw, posterior

Funkcja fwd_bkw przyjmuje następujące argumenty: x jest sekwencją obserwacji, np ['normal', 'cold', 'dizzy'] .; states jest zbiorem stanów ukrytych; a_0 jest prawdopodobieństwem rozpoczęcia; a są prawdopodobieństwami przejścia; i e są prawdopodobieństwami emisji.

Dla uproszczenia kodu, zakładamy, że sekwencja obserwacji x nie jest pusty i że a[i][j] i e[i][j] jest określona dla wszystkich państw i, j.

W działającym przykładzie algorytm naprzód-wstecz jest używany w następujący sposób:

def example():
    return fwd_bkw(observations,
                   states,
                   start_probability,
                   transition_probability,
                   emission_probability,
                   end_state)
>>> for line in example():
...     print(*line)
... 
{'Healthy': 0.3, 'Fever': 0.04000000000000001} {'Healthy': 0.0892, 'Fever': 0.03408} {'Healthy': 0.007518, 'Fever': 0.028120319999999997}
{'Healthy': 0.0010418399999999998, 'Fever': 0.00109578} {'Healthy': 0.00249, 'Fever': 0.00394} {'Healthy': 0.01, 'Fever': 0.01}
{'Healthy': 0.8770110375573259, 'Fever': 0.1229889624426741} {'Healthy': 0.623228030950954, 'Fever': 0.3767719690490461} {'Healthy': 0.2109527048413057, 'Fever': 0.7890472951586943}

Zobacz też

Bibliografia

  • Lawrence R. Rabiner , Samouczek dotyczący ukrytych modeli Markowa i wybranych zastosowań w rozpoznawaniu mowy. Postępowanie IEEE , 77 (2), s. 257–286, luty 1989. 10.1109 / 5.18626
  • Lawrence R. Rabiner, BH Juang (styczeń 1986). „Wprowadzenie do ukrytych modeli Markowa”. Magazyn IEEE ASSP : 4–15.
  • Eugene Charniak (1993). Statystyczna nauka języków . Cambridge, Massachusetts: MIT Press. ISBN   978-0-262-53141-2 .
  • Stuart Russell i Peter Norvig (2010). Artificial Intelligence A Modern Approach 3rd Edition . Upper Saddle River, New Jersey: Pearson Education / Prentice-Hall. ISBN   978-0-13-604259-4 .

Linki zewnętrzne