Changeset 638

Show
Ignore:
Timestamp:
09/27/09 00:58:04 (15 years ago)
Author:
smidl
Message:

redesign of PF and MPF to be more flexible and share more code

Location:
library/bdm/estim
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • library/bdm/estim/particles.cpp

    r487 r638  
    55using std::endl; 
    66 
    7 void PF::bayes ( const vec &dt ) { 
    8         int i; 
    9         vec lls ( n ); 
    10         ivec ind; 
    11         double mlls = -std::numeric_limits<double>::infinity(), sum = 0.0; 
     7void PF::bayes_gensmp(){ 
     8        #pragma parallel for 
     9        for (int i = 0; i < n; i++ ) { 
     10                _samples ( i ) = par->samplecond ( _samples ( i ) ); 
     11                lls(i) = 0; 
     12        } 
     13} 
    1214 
    13         for ( i = 0; i < n; i++ ) { 
    14                 //generate new samples from paramater evolution model; 
    15                 vec old_smp=_samples ( i ); 
    16                 _samples ( i ) = par->samplecond ( old_smp ); 
    17                 lls ( i ) = par->evallogcond ( _samples ( i ), old_smp ); 
    18                 lls ( i ) *= obs->evallogcond ( dt, _samples ( i ) ); 
    19  
    20                 if ( lls ( i ) > mlls ) mlls = lls ( i ); //find maximum 
    21         } 
    22  
     15void PF::bayes_weights(){ 
     16//  
     17        double mlls=max(lls); 
    2318        // compute weights 
    24         for ( i = 0; i < n; i++ ) { 
     19        for (int i = 0; i < n; i++ ) { 
    2520                _w ( i ) *= exp ( lls ( i ) - mlls ); // multiply w by likelihood 
    2621        } 
    2722 
    2823        //renormalize 
     24        double sw=sum(_w); 
     25        if (!isfinite(sw)) { 
     26                for (int i=0;i<n;i++){ 
     27                        if (!isfinite(_w(i))) {_w(i)=0;} 
     28                } 
     29                sw = sum(_w); 
     30                if (!isfinite(sw)) { 
     31                        bdm_error("Particle filter is lost; no particle is good enough."); 
     32                } 
     33        } 
     34        _w /= sw; 
     35} 
     36 
     37void PF::bayes ( const vec &dt ) { 
     38        int i; 
     39        // generate samples - time step 
     40        bayes_gensmp(); 
     41        // weight them - data step 
    2942        for ( i = 0; i < n; i++ ) { 
    30                 sum += _w ( i ); 
    31         }; 
     43                lls ( i ) += obs->evallogcond ( dt, _samples ( i ) ); //+= because lls may have something from gensmp! 
     44        } 
    3245 
    33         _w ( i ) /= sum; //? 
     46        bayes_weights(); 
    3447 
    35         ind = est.resample ( resmethod ); 
     48        if (do_resampling()) { 
     49                est.resample ( resmethod); 
     50        } 
    3651 
    3752} 
     
    4560// } 
    4661 
     62void MPF::bayes ( const vec &dt ) {      
     63        // follows PF::bayes in most places!!! 
     64         
     65        int i; 
     66        int n=pf->__w().length(); 
     67        vec &lls = pf->_lls(); 
     68         
     69        // generate samples - time step 
     70        pf->bayes_gensmp(); 
     71        // weight them - data step 
     72        #pragma parallel for 
     73        for ( i = 0; i < n; i++ ) { 
     74                BMs(i) -> condition(pf->posterior()._sample(i)); 
     75                BMs(i) -> bayes(dt); 
     76                lls ( i ) += BMs(i)->_ll(); 
     77        } 
     78 
     79        pf->bayes_weights(); 
     80         
     81        ivec ind; 
     82        if (pf->do_resampling()) { 
     83                pf->resample ( ind); 
     84                 
     85                #pragma omp parallel for 
     86                for ( i = 0; i < n; i++ ) { 
     87                        if ( ind ( i ) != i ) {//replace the current Bm by a new one 
     88                                delete BMs ( i ); 
     89                                BMs ( i ) = BMs ( ind ( i ) )->_copy_(); //copy constructor 
     90                        } 
     91                }; 
     92        } 
     93}; 
     94 
    4795 
    4896} 
  • library/bdm/estim/particles.h

    r565 r638  
    3636        Array<vec> &_samples; 
    3737        //! Parameter evolution model 
    38         mpdf *par; 
     38        shared_ptr<mpdf> par; 
    3939        //! Observation model 
    40         mpdf *obs; 
    41  
     40        shared_ptr<mpdf> obs; 
     41        //! internal structure storing loglikelihood of predictions 
     42        vec lls; 
     43         
    4244        //! which resampling method will be used 
    4345        RESAMPLING_METHOD resmethod; 
    44  
     46        //! resampling threshold; in this case its meaning is minimum ratio of active particles 
     47        //! For example, for 0.5 resampling is performed when the numebr of active aprticles drops belo 50%. 
     48        double res_threshold; 
     49         
    4550        //! \name Options 
    4651        //!@{ 
     
    5863                LIDs.set_size ( 5 ); 
    5964        }; 
    60         /*      PF ( mpdf *par0, mpdf *obs0, epdf *epdf0, int n0 ) : 
    61                                 est ( ),_w ( est._w() ),_samples ( est._samples() ),opt_L_smp(false), opt_L_wei(false) 
    62                 { set_parameters ( par0,obs0,n0 ); set_statistics ( ones ( n0 ),epdf0 ); };*/ 
    63         void set_parameters ( mpdf *par0, mpdf *obs0, int n0, RESAMPLING_METHOD rm = SYSTEMATIC ) { 
     65         
     66        void set_parameters (int n0, double res_th0=0.5, RESAMPLING_METHOD rm = SYSTEMATIC ) { 
     67                n = n0; 
     68                res_threshold = res_th0; 
     69                resmethod = rm; 
     70        }; 
     71        void set_model ( shared_ptr<mpdf> par0, shared_ptr<mpdf> obs0) { 
    6472                par = par0; 
    6573                obs = obs0; 
    66                 n = n0; 
    67                 resmethod = rm; 
     74                // set values for posterior 
     75                est.set_rv(par->_rv()); 
    6876        }; 
    6977        void set_statistics ( const vec w0, const epdf &epdf0 ) { 
    7078                est.set_statistics ( w0, epdf0 ); 
    7179        }; 
     80        void set_statistics ( const eEmp &epdf0 ) { 
     81                bdm_assert_debug(epdf0._rv().equal(par->_rv()),"Incompatibel input"); 
     82                est=epdf0; 
     83        }; 
    7284        //!@} 
    7385        //! Set posterior density by sampling from epdf0 
    74 //      void set_est ( const epdf &epdf0 ); 
     86        //! Extends original BM::set_options by two more options: 
     87        //! \li logweights - meaning that all weightes will be logged 
     88        //! \li logsamples - all samples will be also logged 
    7589        void set_options ( const string &opt ) { 
    7690                BM::set_options ( opt ); 
     
    7892                opt_L_smp = ( opt.find ( "logsamples" ) != string::npos ); 
    7993        } 
     94        //! bayes I - generate samples and add their weights to lls 
     95        virtual void bayes_gensmp(); 
     96        //! bayes II - compute weights of the  
     97        virtual void bayes_weights(); 
     98        //! important part of particle filtering - decide if it is time to perform resampling 
     99        virtual bool do_resampling(){    
     100                double eff = 1.0 / ( _w * _w ); 
     101                return eff < ( res_threshold*n ); 
     102        } 
    80103        void bayes ( const vec &dt ); 
    81104        //!access function 
    82         vec* __w() { 
    83                 return &_w; 
     105        vec& __w() { return _w; } 
     106        //!access function 
     107        vec& _lls() { return lls; } 
     108        RESAMPLING_METHOD _resmethod() const { return resmethod; } 
     109        //!access function 
     110        const eEmp& posterior() const {return est;} 
     111         
     112        /*! configuration structure for basic PF 
     113        \code 
     114        parameter_pdf   = mpdf_class;         // parameter evolution pdf 
     115        observation_pdf = mpdf_class;         // observation pdf 
     116        prior           = epdf_class;         // prior probability density 
     117        --- optional --- 
     118        n               = 10;                 // number of particles 
     119        resmethod       = 'systematic', or 'multinomial', or 'stratified' 
     120                                                                                  // resampling method 
     121        res_threshold   = 0.5;                // resample when active particles drop below 50% 
     122        \endcode 
     123        */ 
     124        void from_setting(const Setting &set){ 
     125                par = UI::build<mpdf>(set,"parameter_pdf",UI::compulsory); 
     126                obs = UI::build<mpdf>(set,"observation_pdf",UI::compulsory); 
     127                 
     128                prior_from_set(set); 
     129                resmethod_from_set(set); 
     130                // set resampling method 
     131                //set drv 
     132                //find potential input - what remains in rvc when we subtract rv 
     133                RV u = par->_rvc().remove_time().subt( par->_rv() );  
     134                //find potential input - what remains in rvc when we subtract x_t 
     135                RV obs_u = obs->_rvc().remove_time().subt( par->_rv() );  
     136                 
     137                u.add(obs_u); // join both u, and check if they do not overlap 
     138                 
     139                set_drv(concat(obs->_rv(),u) ); 
     140        } 
     141        //! auxiliary function reading parameter 'resmethod' from configuration file 
     142        void resmethod_from_set(const Setting &set){ 
     143                string resmeth; 
     144                if (UI::get(resmeth,set,"resmethod",UI::optional)){ 
     145                        if (resmeth=="systematic") { 
     146                                resmethod= SYSTEMATIC; 
     147                        } else  { 
     148                                if (resmeth=="multinomial"){ 
     149                                        resmethod=MULTINOMIAL; 
     150                                } else { 
     151                                        if (resmeth=="stratified"){ 
     152                                                resmethod= STRATIFIED; 
     153                                        } else { 
     154                                                bdm_error("Unknown resampling method"); 
     155                                        } 
     156                                } 
     157                        } 
     158                } else { 
     159                        resmethod=SYSTEMATIC; 
     160                }; 
     161                if(!UI::get(res_threshold, set, "res_threshold", UI::optional)){ 
     162                        res_threshold=0.5; 
     163                } 
     164        } 
     165        //! load prior information from set and set internal structures accordingly 
     166        void prior_from_set(const Setting & set){ 
     167                shared_ptr<epdf> pri = UI::build<epdf>(set,"prior",UI::compulsory); 
     168                 
     169                eEmp *test_emp=dynamic_cast<eEmp*>(&(*pri)); 
     170                if (test_emp) { // given pdf is sampled 
     171                        est=*test_emp; 
     172                } else { 
     173                        int n; 
     174                        if (!UI::get(n,set,"n",UI::optional)){n=10;} 
     175                        // sample from prior 
     176                        set_statistics(ones(n)/n, *pri); 
     177                } 
     178                //validate(); 
     179        } 
     180         
     181        void validate(){ 
     182                n=_w.length(); 
     183                lls=zeros(n); 
     184                if (par->_rv()._dsize()>0) { 
     185                        bdm_assert(par->_rv()._dsize()==est.dimension(),"Mismatch of RV and dimension of posterior" ); 
     186                } 
     187        } 
     188        //! resample posterior density (from outside - see MPF) 
     189        void resample(ivec &ind){ 
     190                est.resample(ind,resmethod); 
    84191        } 
    85192}; 
     193UIREGISTER(PF); 
    86194 
    87195/*! 
    88196\brief Marginalized Particle filter 
    89197 
    90 Trivial version: proposal = parameter evolution, observation model is not used. (it is assumed to be part of BM). 
     198A composition of particle filter with exact (or almost exact) bayesian models (BMs). 
     199The Bayesian models provide marginalized predictive density. Internaly this is achieved by virtual class MPFmpdf. 
    91200*/ 
    92201 
    93 template<class BM_T> 
    94 class MPF : public PF { 
    95         Array<BM_T*> BMs; 
     202class MPF : public BM  { 
     203    shared_ptr<PF> pf; 
     204        Array<BM*> BMs; 
    96205 
    97206        //! internal class for MPDF providing composition of eEmp with external components 
    98207 
    99208        class mpfepdf : public epdf  { 
    100         protected: 
    101                 eEmp &E; 
    102                 vec &_w; 
    103                 Array<const epdf*> Coms; 
     209                shared_ptr<PF> &pf; 
     210                Array<BM*> &BMs; 
    104211        public: 
    105                 mpfepdf ( eEmp &E0 ) : 
    106                                 epdf ( ), E ( E0 ),  _w ( E._w() ), 
    107                                 Coms ( _w.length() ) { 
    108                 }; 
    109                 //! read statistics from MPF 
    110                 void read_statistics ( Array<BM_T*> &A ) { 
    111                         dim = E.dimension() + A ( 0 )->posterior().dimension(); 
    112                         for ( int i = 0; i < _w.length() ; i++ ) { 
    113                                 Coms ( i ) = &(A ( i )->posterior()); 
     212                mpfepdf (shared_ptr<PF> &pf0, Array<BM*> &BMs0): epdf(), pf(pf0), BMs(BMs0) { }; 
     213                //! a variant of set parameters - this time, parameters are read from BMs and pf 
     214                void read_parameters(){ 
     215                        rv = concat(pf->posterior()._rv(), BMs(0)->posterior()._rv()); 
     216                        dim = pf->posterior().dimension() + BMs(0)->posterior().dimension(); 
     217                        bdm_assert_debug(dim == rv._dsize(), "Wrong name "); 
     218                } 
     219                vec mean() const { 
     220                        const vec &w = pf->posterior()._w(); 
     221                        vec pom = zeros ( BMs(0)->posterior ().dimension() ); 
     222                        //compute mean of BMs 
     223                        for ( int i = 0; i < w.length(); i++ ) { 
     224                                pom += BMs ( i )->posterior().mean() * w ( i ); 
    114225                        } 
    115                 } 
    116                 //! needed in resampling 
    117                 void set_elements ( int &i, double wi, const epdf* ep ) { 
    118                         _w ( i ) = wi; 
    119                         Coms ( i ) = ep; 
    120                 }; 
    121  
    122                 void set_parameters ( int n ) { 
    123                         E.set_parameters ( n, false ); 
    124                         Coms.set_length ( n ); 
    125                 } 
    126                 vec mean() const { 
    127                         // ugly 
    128                         vec pom = zeros ( Coms ( 0 )->dimension() ); 
    129                         for ( int i = 0; i < _w.length(); i++ ) { 
    130                                 pom += Coms ( i )->mean() * _w ( i ); 
     226                        return concat ( pf->posterior().mean(), pom ); 
     227                } 
     228                vec variance() const { 
     229                        const vec &w = pf->posterior()._w(); 
     230                         
     231                        vec pom = zeros ( BMs(0)->posterior ().dimension() ); 
     232                        vec pom2 = zeros ( BMs(0)->posterior ().dimension() ); 
     233                        vec mea; 
     234                         
     235                        for ( int i = 0; i < w.length(); i++ ) { 
     236                                // save current mean  
     237                                mea = BMs ( i )->posterior().mean(); 
     238                                pom += mea * w ( i ); 
     239                                //compute variance 
     240                                pom2 += ( BMs ( i )->posterior().variance() + pow ( mea, 2 ) ) * w ( i ); 
    131241                        } 
    132                         return concat ( E.mean(), pom ); 
    133                 } 
    134                 vec variance() const { 
    135                         // ugly 
    136                         vec pom = zeros ( Coms ( 0 )->dimension() ); 
    137                         vec pom2 = zeros ( Coms ( 0 )->dimension() ); 
    138                         for ( int i = 0; i < _w.length(); i++ ) { 
    139                                 pom += Coms ( i )->mean() * _w ( i ); 
    140                                 pom2 += ( Coms ( i )->variance() + pow ( Coms ( i )->mean(), 2 ) ) * _w ( i ); 
    141                         } 
    142                         return concat ( E.variance(), pom2 - pow ( pom, 2 ) ); 
    143                 } 
     242                        return concat ( pf->posterior().variance(), pom2 - pow ( pom, 2 ) ); 
     243                } 
     244                 
    144245                void qbounds ( vec &lb, vec &ub, double perc = 0.95 ) const { 
    145246                        //bounds on particles 
    146247                        vec lbp; 
    147248                        vec ubp; 
    148                         E.qbounds ( lbp, ubp ); 
     249                        pf->posterior().qbounds ( lbp, ubp ); 
    149250 
    150251                        //bounds on Components 
    151                         int dimC = Coms ( 0 )->dimension(); 
     252                        int dimC = BMs ( 0 )->posterior().dimension(); 
    152253                        int j; 
    153254                        // temporary 
     
    160261                        Ubc = -std::numeric_limits<double>::infinity(); 
    161262 
    162                         for ( int i = 0; i < _w.length(); i++ ) { 
     263                        for ( int i = 0; i < BMs.length(); i++ ) { 
    163264                                // check Coms 
    164                                 Coms ( i )->qbounds ( lbc, ubc ); 
     265                                BMs ( i )->posterior().qbounds ( lbc, ubc ); 
     266                                //save either minima or maxima 
    165267                                for ( j = 0; j < dimC; j++ ) { 
    166268                                        if ( lbc ( j ) < Lbc ( j ) ) { 
     
    195297public: 
    196298        //! Default constructor. 
    197         MPF () : PF (), jest ( est ) {}; 
    198         void set_parameters ( mpdf *par0, mpdf *obs0, int n0, RESAMPLING_METHOD rm = SYSTEMATIC ) { 
    199                 PF::set_parameters ( par0, obs0, n0, rm ); 
    200                 jest.set_parameters ( n0 );//duplication of rm 
     299        MPF () :  jest (pf,BMs) {}; 
     300        void set_parameters ( shared_ptr<mpdf> par0, shared_ptr<mpdf> obs0, int n0, RESAMPLING_METHOD rm = SYSTEMATIC ) { 
     301                pf->set_model ( par0, obs0);  
     302                pf->set_parameters(n0, rm ); 
    201303                BMs.set_length ( n0 ); 
    202304        } 
    203         void set_statistics ( const epdf &epdf0, const BM_T* BMcond0 ) { 
    204  
    205                 PF::set_statistics ( ones ( n ) / n, epdf0 ); 
     305        void set_BM ( const BM &BMcond0 ) { 
     306 
     307                int n=pf->__w().length(); 
     308                BMs.set_length(n); 
    206309                // copy 
     310                //BMcond0 .condition ( pf->posterior()._sample ( 0 ) ); 
    207311                for ( int i = 0; i < n; i++ ) { 
    208                         BMs ( i ) = new BM_T ( *BMcond0 ); 
    209                         BMs ( i )->condition ( _samples ( i ) ); 
    210                 } 
    211  
    212                 jest.read_statistics ( BMs ); 
    213                 //options 
     312                        BMs ( i ) = BMcond0._copy_(); 
     313                        BMs ( i )->condition ( pf->posterior()._sample ( i ) ); 
     314                } 
    214315        }; 
    215316 
     
    218319                return jest; 
    219320        } 
    220         //! Set postrior of \c rvc to samples from epdf0. Statistics of BMs are not re-computed! Use only for initialization! 
    221         /*      void set_est ( const epdf& epdf0 ) { 
    222                         PF::set_est ( epdf0 );  // sample params in condition 
    223                         // copy conditions to BMs 
    224  
    225                         for ( int i=0;i<n;i++ ) {BMs(i)->condition ( _samples ( i ) );} 
    226                 }*/ 
     321        //! Extends options understood by BM::set_options by option  
     322        //! \li logmeans - meaning  
    227323        void set_options ( const string &opt ) { 
    228                 PF::set_options ( opt ); 
     324                BM::set_options(opt); 
    229325                opt_L_mea = ( opt.find ( "logmeans" ) != string::npos ); 
    230326        } 
     
    234330                return BMs ( i ); 
    235331        } 
     332         
     333        /*! configuration structure for basic PF 
     334        \code 
     335        BM              = BM_class;           // Bayesian filtr for analytical part of the model 
     336        parameter_pdf   = mpdf_class;         // transitional pdf for non-parametric part of the model 
     337        prior           = epdf_class;         // prior probability density 
     338        --- optional --- 
     339        n               = 10;                 // number of particles 
     340        resmethod       = 'systematic', or 'multinomial', or 'stratified' 
     341                                                                                  // resampling method 
     342        \endcode 
     343        */       
     344        void from_setting(const Setting &set){ 
     345                shared_ptr<mpdf> par = UI::build<mpdf>(set,"parameter_pdf",UI::compulsory); 
     346                shared_ptr<mpdf> obs= new mpdf(); // not used!! 
     347 
     348                pf = new PF; 
     349                // rpior must be set before BM 
     350                pf->prior_from_set(set); 
     351                pf->resmethod_from_set(set); 
     352                pf->set_model(par,obs); 
     353                 
     354                shared_ptr<BM> BM0 =UI::build<BM>(set,"BM",UI::compulsory); 
     355                set_BM(*BM0); 
     356                 
     357                string opt; 
     358                if (UI::get(opt,set,"options",UI::optional)){ 
     359                        set_options(opt); 
     360                } 
     361                //set drv 
     362                //find potential input - what remains in rvc when we subtract rv 
     363                RV u = par->_rvc().remove_time().subt( par->_rv() );             
     364                set_drv(concat(BM0->_drv(),u) ); 
     365                validate(); 
     366        } 
     367        void validate(){ 
     368                try{ 
     369                pf->validate(); 
     370                } catch (std::exception &e){ 
     371                        throw UIException("Error in PF part of MPF:"); 
     372                } 
     373                jest.read_parameters(); 
     374        } 
     375         
    236376}; 
    237  
    238 template<class BM_T> 
    239 void MPF<BM_T>::bayes ( const vec &dt ) { 
    240         int i; 
    241         vec lls ( n ); 
    242         vec llsP ( n ); 
    243         ivec ind; 
    244         double mlls = -std::numeric_limits<double>::infinity(); 
    245  
    246 #pragma omp parallel for 
    247         for ( i = 0; i < n; i++ ) { 
    248                 //generate new samples from paramater evolution model; 
    249                 vec old_smp=_samples ( i ); 
    250                 _samples ( i ) = par->samplecond ( old_smp ); 
    251                 llsP ( i ) = par->evallogcond ( _samples ( i ), old_smp ); 
    252                 BMs ( i )->condition ( _samples ( i ) ); 
    253                 BMs ( i )->bayes ( dt ); 
    254                 lls ( i ) = BMs ( i )->_ll(); // lls above is also in proposal her must be lls(i) =, not +=!! 
    255                 if ( lls ( i ) > mlls ) mlls = lls ( i ); //find maximum likelihood (for numerical stability) 
    256         } 
    257  
    258         double sum_w = 0.0; 
    259         // compute weights 
    260 #pragma omp parallel for 
    261         for ( i = 0; i < n; i++ ) { 
    262                 _w ( i ) *= exp ( lls ( i ) - mlls ); // multiply w by likelihood 
    263                 sum_w += _w ( i ); 
    264         } 
    265  
    266         if ( sum_w  > 0.0 ) { 
    267                 _w /= sum_w; //? 
    268         } else { 
    269                 cout << "sum(w)==0" << endl; 
    270         } 
    271  
    272  
    273         double eff = 1.0 / ( _w * _w ); 
    274         if ( eff < ( 0.3*n ) ) { 
    275                 ind = est.resample ( resmethod ); 
    276                 // Resample Bms! 
    277  
    278 #pragma omp parallel for 
    279                 for ( i = 0; i < n; i++ ) { 
    280                         if ( ind ( i ) != i ) {//replace the current Bm by a new one 
    281                                 //fixme this would require new assignment operator 
    282                                 // *Bms[i] = *Bms[ind ( i ) ]; 
    283  
    284                                 // poor-man's solution: replicate constructor here 
    285                                 // copied from MPF::MPF 
    286                                 delete BMs ( i ); 
    287                                 BMs ( i ) = new BM_T ( *BMs ( ind ( i ) ) ); //copy constructor 
    288                                 const epdf& pom = BMs ( i )->posterior(); 
    289                                 jest.set_elements ( i, 1.0 / n, &pom ); 
    290                         } 
    291                 }; 
    292                 cout << '.'; 
    293         } 
    294 } 
     377UIREGISTER(MPF); 
    295378 
    296379}