2012-05-03 14 views
13

Interesuje mnie prosty algorytm filtrowania cząstek podany tutaj: http://www.aiqus.com/upfiles/PFAlgo.png Wydaje się bardzo prosty, ale nie mam pojęcia, jak to zrobić praktycznie. Każdy pomysł, jak go wdrożyć (aby lepiej zrozumieć, jak to działa)?Implementacja sekwencyjnej metody Monte Carlo (filtry cząstek stałych)

Edit: To wielki prosty przykład, który wyjaśnia, jak to działa: http://www.aiqus.com/questions/39942/very-simple-particle-filters-algorithm-sequential-monte-carlo-method-implementation?page=1#39950

starałem się wdrożyć go w C++: http://pastebin.com/M1q1HcN4 ale jestem pewien, czy pamiętać zrobić to we właściwy sposób . Czy możesz sprawdzić, czy dobrze to zrozumiałem, czy też według mojego kodu są jakieś nieporozumienia?

#include <iostream> 
#include <vector> 
#include <boost/random/mersenne_twister.hpp> 
#include <boost/random/uniform_01.hpp> 
#include <boost/random/uniform_int_distribution.hpp> 

using namespace std; 
using namespace boost; 

double uniform_generator(void); 

#define N 4 // number of particles 

#define evolutionProba_A_A 1.0/3.0 // P(X_t = A | X_t-1 = A) 
#define evolutionProba_A_B 1.0/3.0 // P(X_t = A | X_t-1 = B) 
#define evolutionProba_B_B 2.0/3.0 // P(X_t = B | X_t-1 = B) 
#define evolutionProba_B_A 2.0/3.0 // P(X_t = B | X_t-1 = A) 

#define observationProba_A_A 4.0/5.0 // P(Y_t = A | X_t = A) 
#define observationProba_A_B 1.0/5.0 // P(Y_t = A | X_t = B) 
#define observationProba_B_B 4.0/5.0 // P(Y_t = B | X_t = B) 
#define observationProba_B_A 1.0/5.0 // P(Y_t = A | X_t = A) 

/// =========================================================================== 

typedef struct distrib { float PA; float PB; } Distribution; 

typedef struct particle 
{ 
    Distribution distribution; // e.g. <0.5, 0.5> 
    char state; // e.g. 'A' or 'B' 
    float weight; // e.g. 0.8 
} 
Particle; 

/// =========================================================================== 

int main() 
{ 
    vector<char> Y; // data observations 
    Y.push_back('A'); Y.push_back('B'); Y.push_back('A'); Y.push_back('A'); Y.push_back('A'); Y.push_back('B'); 
    Y.push_back('A'); Y.push_back('A'); Y.push_back('B'); Y.push_back('A'); Y.push_back('B'); Y.push_back('A'); 
    Y.push_back('A'); Y.push_back('B'); Y.push_back('B'); Y.push_back('A'); Y.push_back('A'); Y.push_back('B'); 

    vector< vector<Particle> > Xall; // vector of all particles from time 0 to t 

    /// Step (1) Initialisation 
    vector<Particle> X; // a vector of N particles 
    for(int i = 0; i < N; ++i) 
    { 
     Particle x; 

     // sample particle Xi from initial distribution 
     x.distribution.PA = 0.5; x.distribution.PB = 0.5; 
     float r = uniform_generator(); 
     if(r <= x.distribution.PA) x.state = 'A'; // r <= 0.5 
     if(x.distribution.PA < r && r <= x.distribution.PA + x.distribution.PB) x.state = 'B'; // 0.5 < r <= 1 

     X.push_back(x); 
    } 

    Xall.push_back(X); 
    X.clear(); 

    /// Observing data 
    for(int t = 1; t <= 18; ++t) 
    { 
     char y = Y[t-1]; // current observation 

     /// Step (2) Importance sampling 
     float sumWeights = 0; 
     vector<Particle> X; // a vector of N particles 
     for(int i = 0; i < N; ++i) 
     { 
      Particle x; 

      // P(X^i_t = A) = P(X^i_t = A | X^i_t-1 = A) * P(X^i_t-1 = A) + P(X^i_t = A | X^i_t-1 = B) * P(X^i_t-1 = B) 
      x.distribution.PA = evolutionProba_A_A * Xall[t-1][i].distribution.PA + evolutionProba_A_B * Xall[t-1][i].distribution.PB; 

      // P(X^i_t = B) = P(X^i_t = B | X^i_t-1 = A) * P(X^i_t-1 = A) + P(X^i_t = B | X^i_t-1 = B) * P(X^i_t-1 = B) 
      x.distribution.PB = evolutionProba_B_A * Xall[t-1][i].distribution.PA + evolutionProba_B_B * Xall[t-1][i].distribution.PB; 

      // sample the a particle from this distribution 
      float r = uniform_generator(); 
      if(r <= x.distribution.PA) x.state = 'A'; 
      if(x.distribution.PA < r && r <= x.distribution.PA + x.distribution.PB) x.state = 'B'; 

      // compute weight of this particle according to the observation y 
      if(y == 'A') 
      { 
       if(x.state == 'A') x.weight = observationProba_A_A; // P(y = A | X^i_t = A) 
       else if(x.state == 'B') x.weight = observationProba_A_B; // P(y = A | X^i_t = B) 
      } 
      else if(y == 'B') 
      { 
       if(x.state == 'A') x.weight = observationProba_B_A; // P(y = B | X^i_t = A) 
       else if(x.state == 'B') x.weight = observationProba_B_B; // P(y = B | X^i_t = B) 
      } 

      sumWeights += x.weight; 

      X.push_back(x); 
     } 

     // normalise weights 
     for(int i = 0; i < N; ++i) 
      X[i].weight /= sumWeights; 

     /// Step (3) resampling N particles according to weights 
     float PA = 0, PB = 0; 
     for(int i = 0; i < N; ++i) 
     { 
      if(X[i].state == 'A') PA += X[i].weight; 
      else if(X[i].state == 'B') PB += X[i].weight; 
     } 

     vector<Particle> reX; // new vector of particles 
     for(int i = 0; i < N; ++i) 
     { 
      Particle x; 

      x.distribution.PA = PA; 
      x.distribution.PB = PB; 

      float r = uniform_generator(); 
      if(r <= x.distribution.PA) x.state = 'A'; 
      if(x.distribution.PA < r && r <= x.distribution.PA + x.distribution.PB) x.state = 'B'; 

      reX.push_back(x); 
     } 

     Xall.push_back(reX); 
    } 

    return 0; 
} 

/// =========================================================================== 

double uniform_generator(void) 
{ 
    mt19937 gen(55); 
    static uniform_01< mt19937, double > uniform_gen(gen); 
    return uniform_gen(); 
} 
+0

Kiedy możesz filtrować w prawdziwym świecie? Czy możesz przeprowadzić test na problem z rozwiązaniem analitycznym? Jeśli poprawnie zaimplementowałeś, otrzymasz ten sam numer. Jest bardzo mało prawdopodobne, aby uzyskać prawidłowy wynik ze złym wdrożeniem! –

+0

@AlessandroTeruzzi Jest to tylko przykładowy przykład [here] (http://www.aiqus.com/questions/39942/very-simple-particle-filters-algorithm-sequential-monte-carlo-method-implementation/39950). Wdrożyłem go tylko po to, aby lepiej zrozumieć [koncepcję filtrów cząstek podanych przez ten algorytm] (http://www.aiqus.com/upfiles/PFAlgo.png), ale nie jestem pewien, czy zaimplementowałem go poprawnie, ponieważ Nie zrozumiałem tego algorytmu bardzo dobrze. Nie wiem, jak sprawdzić, czy to działa, ponieważ algorytm i jego wynik nadal nie jest dla mnie zbyt jasny (nawet jeśli algorytm wydaje się bardzo prosty). – shn

+0

Moja pierwsza sugestia dotycząca ogólnego algorytmu: nie próbuj implementować czegoś, czego nie rozumiesz w pełni. Najpierw podbij, a następnie zaimplementuj. W przeciwnym razie nie będziesz w stanie powiedzieć, co dzieje się źle. –

Odpowiedz

20

This online course jest bardzo łatwy i zrozumiały, a dla mnie wyjaśnił bardzo dobrze filtry cząstek stałych.

To się nazywa "Programowanie samochodu robotycznego" i mówi o trzech metodach loklizacji: lokalizacji Monte Carlo, filtrach Kalmana i filtrach cząstek.

Kurs jest całkowicie darmowy (jest już gotowy, więc nie można aktywnie uczestniczyć, ale nadal można oglądać wykłady), prowadzony przez profesora Stanforda. "Zajęcia" były dla mnie zaskakująco łatwe do wykonania, a towarzyszą im małe ćwiczenia - niektóre z nich są po prostu logiczne, ale sporo z nich programuje. Również zadania domowe, z którymi możesz się bawić.

To faktycznie sprawia, że ​​piszesz własny kod w pythonie dla wszystkich filtrów, które również testują dla ciebie. Pod koniec kursu powinieneś mieć wszystkie 3 filtry zaimplementowane w pythonie.

Gorąco polecam to sprawdzić.

+0

OK, sprawdzę to. Ale ponieważ interesują mnie tylko filtry cząstek stałych (może także dwa inne filtry), czy powinienem od początku sprawdzić wszystkie kursy wszystkich jednostek? – shn

+0

Jeśli interesują Cię wszystkie filtry, zdecydowanie sprawdź cały kurs. Ale nawet jeśli nie jesteś, polecam przejść drugi kurs - da Ci to bardzo dobry ogólny przegląd metod lokalizacji, a łatwiej zorientujesz się, gdzie każdy z filtrów jest najbardziej odpowiedni. Myślę, że 1 wykład można zwykle zrobić w około 4 godziny - może zrobić to przez 1 lub 2 dni, jeśli chce się to łatwo;) – penelope

+0

Nawiasem mówiąc, nie będę używał filtrów cząstek dla robotyki (lokalizacja itp.), I użyje go do innego problemu związanego z klastrowaniem w trybie online danych sekwencyjnych. – shn

3
+0

Nie są w jakiś sposób tym, czego się spodziewałem. Czy istnieje sposób wdrożenia prostego, przedstawionego na stronie 9 www.cs.ubc.ca/~ arnaud/doucet_defreitas_gordon_smcbookintro.ps? – shn

+0

Oczywiście, są sposoby :) W jaki sposób linki różnią się od twoich oczekiwań? Gdzie się rozłączasz? Wierzę, że algorytm na s. 11. jest dość prosty. – Throwback1986

+0

Cóż, chcę zaimplementować filtry cząsteczek, które są dostępne na podstawie scrach, aby je zrozumieć. Zmienilem swój pierwszy post, aby dodać prostą implementację C++ prostego przykładu wyjaśnionego tutaj: http://www.aiqus.com/questions/39942/very-simple-particle-filters-algorithm-sequential-monte-carlo- metoda-implementacja? strona = 1 # 39950 Czy możesz sprawdzić, czy dobrze to zrozumiałem, czy są jakieś nieporozumienia? – shn