root/library/bdm/estim/particles.h @ 686

Revision 686, 10.9 kB (checked in by smidl, 15 years ago)

pmsm using new syntax for bayes

  • Property svn:eol-style set to native
RevLine 
[8]1/*!
2  \file
3  \brief Bayesian Filtering using stochastic sampling (Particle Filters)
4  \author Vaclav Smidl.
5
6  -----------------------------------
7  BDM++ - C++ library for Bayesian Decision Making under Uncertainty
8
9  Using IT++ for numerical operations
10  -----------------------------------
11*/
12
[384]13#ifndef PARTICLES_H
14#define PARTICLES_H
[8]15
[262]16
[384]17#include "../stat/exp_family.h"
[8]18
[270]19namespace bdm {
[8]20
21/*!
[32]22* \brief Trivial particle filter with proposal density equal to parameter evolution model.
[8]23
[32]24Posterior density is represented by a weighted empirical density (\c eEmp ).
[8]25*/
[32]26
27class PF : public BM {
[8]28protected:
[32]29        //!number of particles;
30        int n;
31        //!posterior density
32        eEmp est;
33        //! pointer into \c eEmp
34        vec &_w;
35        //! pointer into \c eEmp
36        Array<vec> &_samples;
37        //! Parameter evolution model
[638]38        shared_ptr<mpdf> par;
[32]39        //! Observation model
[638]40        shared_ptr<mpdf> obs;
41        //! internal structure storing loglikelihood of predictions
42        vec lls;
43       
[283]44        //! which resampling method will be used
45        RESAMPLING_METHOD resmethod;
[638]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       
[281]50        //! \name Options
51        //!@{
52        //!@}
53
[8]54public:
[270]55        //! \name Constructors
56        //!@{
[676]57        PF ( ) : est(), _w ( est._w() ), _samples ( est._samples() ) {
[477]58        };
[638]59       
60        void set_parameters (int n0, double res_th0=0.5, RESAMPLING_METHOD rm = SYSTEMATIC ) {
[477]61                n = n0;
[638]62                res_threshold = res_th0;
[477]63                resmethod = rm;
64        };
[638]65        void set_model ( shared_ptr<mpdf> par0, shared_ptr<mpdf> obs0) {
66                par = par0;
67                obs = obs0;
68                // set values for posterior
69                est.set_rv(par->_rv());
70        };
[488]71        void set_statistics ( const vec w0, const epdf &epdf0 ) {
[477]72                est.set_statistics ( w0, epdf0 );
73        };
[638]74        void set_statistics ( const eEmp &epdf0 ) {
75                bdm_assert_debug(epdf0._rv().equal(par->_rv()),"Incompatibel input");
76                est=epdf0;
77        };
[270]78        //!@}
[33]79        //! Set posterior density by sampling from epdf0
[638]80        //! Extends original BM::set_options by two more options:
81        //! \li logweights - meaning that all weightes will be logged
82        //! \li logsamples - all samples will be also logged
[283]83        void set_options ( const string &opt ) {
[477]84                BM::set_options ( opt );
[281]85        }
[638]86        //! bayes I - generate samples and add their weights to lls
[665]87        virtual void bayes_gensmp(const vec &ut);
[638]88        //! bayes II - compute weights of the
89        virtual void bayes_weights();
90        //! important part of particle filtering - decide if it is time to perform resampling
91        virtual bool do_resampling(){   
92                double eff = 1.0 / ( _w * _w );
93                return eff < ( res_threshold*n );
94        }
[679]95        void bayes ( const vec &yt, const vec &cond );
[225]96        //!access function
[638]97        vec& __w() { return _w; }
98        //!access function
99        vec& _lls() { return lls; }
[660]100        //!access function
[638]101        RESAMPLING_METHOD _resmethod() const { return resmethod; }
[660]102        //! return correctly typed posterior (covariant return)
[638]103        const eEmp& posterior() const {return est;}
104       
105        /*! configuration structure for basic PF
106        \code
107        parameter_pdf   = mpdf_class;         // parameter evolution pdf
108        observation_pdf = mpdf_class;         // observation pdf
109        prior           = epdf_class;         // prior probability density
110        --- optional ---
111        n               = 10;                 // number of particles
112        resmethod       = 'systematic', or 'multinomial', or 'stratified'
113                                                                                  // resampling method
114        res_threshold   = 0.5;                // resample when active particles drop below 50%
115        \endcode
116        */
117        void from_setting(const Setting &set){
[665]118                BM::from_setting(set);
[638]119                par = UI::build<mpdf>(set,"parameter_pdf",UI::compulsory);
120                obs = UI::build<mpdf>(set,"observation_pdf",UI::compulsory);
121               
122                prior_from_set(set);
123                resmethod_from_set(set);
124                // set resampling method
125                //set drv
126                //find potential input - what remains in rvc when we subtract rv
127                RV u = par->_rvc().remove_time().subt( par->_rv() ); 
128                //find potential input - what remains in rvc when we subtract x_t
129                RV obs_u = obs->_rvc().remove_time().subt( par->_rv() ); 
130               
131                u.add(obs_u); // join both u, and check if they do not overlap
[665]132
[686]133                set_yrv(obs->_rv() );
134                rvc = u;
[477]135        }
[638]136        //! auxiliary function reading parameter 'resmethod' from configuration file
137        void resmethod_from_set(const Setting &set){
138                string resmeth;
139                if (UI::get(resmeth,set,"resmethod",UI::optional)){
140                        if (resmeth=="systematic") {
141                                resmethod= SYSTEMATIC;
142                        } else  {
143                                if (resmeth=="multinomial"){
144                                        resmethod=MULTINOMIAL;
145                                } else {
146                                        if (resmeth=="stratified"){
147                                                resmethod= STRATIFIED;
148                                        } else {
149                                                bdm_error("Unknown resampling method");
150                                        }
151                                }
152                        }
153                } else {
154                        resmethod=SYSTEMATIC;
155                };
156                if(!UI::get(res_threshold, set, "res_threshold", UI::optional)){
157                        res_threshold=0.5;
158                }
[665]159                validate();
[638]160        }
161        //! load prior information from set and set internal structures accordingly
162        void prior_from_set(const Setting & set){
163                shared_ptr<epdf> pri = UI::build<epdf>(set,"prior",UI::compulsory);
164               
165                eEmp *test_emp=dynamic_cast<eEmp*>(&(*pri));
166                if (test_emp) { // given pdf is sampled
167                        est=*test_emp;
168                } else {
[665]169                        //int n;
[638]170                        if (!UI::get(n,set,"n",UI::optional)){n=10;}
171                        // sample from prior
172                        set_statistics(ones(n)/n, *pri);
173                }
[665]174                n = est._w().length();
[638]175                //validate();
176        }
177       
178        void validate(){
179                n=_w.length();
180                lls=zeros(n);
181                if (par->_rv()._dsize()>0) {
182                        bdm_assert(par->_rv()._dsize()==est.dimension(),"Mismatch of RV and dimension of posterior" );
183                }
184        }
185        //! resample posterior density (from outside - see MPF)
186        void resample(ivec &ind){
187                est.resample(ind,resmethod);
188        }
[660]189        //! access function
[653]190        Array<vec>& __samples(){return _samples;}
[8]191};
[638]192UIREGISTER(PF);
[8]193
194/*!
[32]195\brief Marginalized Particle filter
[8]196
[638]197A composition of particle filter with exact (or almost exact) bayesian models (BMs).
198The Bayesian models provide marginalized predictive density. Internaly this is achieved by virtual class MPFmpdf.
[8]199*/
200
[638]201class MPF : public BM  {
[653]202        protected:
[660]203                //! particle filter on non-linear variable
[653]204        shared_ptr<PF> pf;
[660]205        //! Array of Bayesian models
[638]206        Array<BM*> BMs;
[32]207
208        //! internal class for MPDF providing composition of eEmp with external components
209
[477]210        class mpfepdf : public epdf  {
[660]211                //! pointer to particle filter
[638]212                shared_ptr<PF> &pf;
[660]213                //! pointer to Array of BMs
[638]214                Array<BM*> &BMs;
[8]215        public:
[660]216                //! constructor
[638]217                mpfepdf (shared_ptr<PF> &pf0, Array<BM*> &BMs0): epdf(), pf(pf0), BMs(BMs0) { };
218                //! a variant of set parameters - this time, parameters are read from BMs and pf
219                void read_parameters(){
220                        rv = concat(pf->posterior()._rv(), BMs(0)->posterior()._rv());
221                        dim = pf->posterior().dimension() + BMs(0)->posterior().dimension();
222                        bdm_assert_debug(dim == rv._dsize(), "Wrong name ");
[283]223                }
[32]224                vec mean() const {
[638]225                        const vec &w = pf->posterior()._w();
226                        vec pom = zeros ( BMs(0)->posterior ().dimension() );
227                        //compute mean of BMs
228                        for ( int i = 0; i < w.length(); i++ ) {
229                                pom += BMs ( i )->posterior().mean() * w ( i );
[477]230                        }
[638]231                        return concat ( pf->posterior().mean(), pom );
[32]232                }
[229]233                vec variance() const {
[638]234                        const vec &w = pf->posterior()._w();
235                       
236                        vec pom = zeros ( BMs(0)->posterior ().dimension() );
237                        vec pom2 = zeros ( BMs(0)->posterior ().dimension() );
238                        vec mea;
239                       
240                        for ( int i = 0; i < w.length(); i++ ) {
241                                // save current mean
242                                mea = BMs ( i )->posterior().mean();
243                                pom += mea * w ( i );
244                                //compute variance
245                                pom2 += ( BMs ( i )->posterior().variance() + pow ( mea, 2 ) ) * w ( i );
[270]246                        }
[638]247                        return concat ( pf->posterior().variance(), pom2 - pow ( pom, 2 ) );
[229]248                }
[638]249               
[477]250                void qbounds ( vec &lb, vec &ub, double perc = 0.95 ) const {
[283]251                        //bounds on particles
252                        vec lbp;
253                        vec ubp;
[638]254                        pf->posterior().qbounds ( lbp, ubp );
[32]255
[283]256                        //bounds on Components
[638]257                        int dimC = BMs ( 0 )->posterior().dimension();
[283]258                        int j;
259                        // temporary
[477]260                        vec lbc ( dimC );
261                        vec ubc ( dimC );
[283]262                        // minima and maxima
[477]263                        vec Lbc ( dimC );
264                        vec Ubc ( dimC );
[283]265                        Lbc = std::numeric_limits<double>::infinity();
266                        Ubc = -std::numeric_limits<double>::infinity();
267
[638]268                        for ( int i = 0; i < BMs.length(); i++ ) {
[283]269                                // check Coms
[638]270                                BMs ( i )->posterior().qbounds ( lbc, ubc );
271                                //save either minima or maxima
[477]272                                for ( j = 0; j < dimC; j++ ) {
273                                        if ( lbc ( j ) < Lbc ( j ) ) {
274                                                Lbc ( j ) = lbc ( j );
275                                        }
276                                        if ( ubc ( j ) > Ubc ( j ) ) {
277                                                Ubc ( j ) = ubc ( j );
278                                        }
[283]279                                }
280                        }
[477]281                        lb = concat ( lbp, Lbc );
282                        ub = concat ( ubp, Ubc );
[283]283                }
284
[477]285                vec sample() const {
[565]286                        bdm_error ( "Not implemented" );
287                        return vec();
[477]288                }
[32]289
[477]290                double evallog ( const vec &val ) const {
[565]291                        bdm_error ( "not implemented" );
[477]292                        return 0.0;
293                }
[32]294        };
295
[281]296        //! Density joining PF.est with conditional parts
[32]297        mpfepdf jest;
298
[679]299        //! datalink from global yt and cond (Up) to BMs yt and cond (Down)
300        datalink_m2m this2bm;
301        //! datalink from global yt and cond (Up) to PFs yt and cond (Down)
302        datalink_m2m this2pf;
303       
[32]304public:
305        //! Default constructor.
[638]306        MPF () :  jest (pf,BMs) {};
[660]307        //! set all parameters at once
[638]308        void set_parameters ( shared_ptr<mpdf> par0, shared_ptr<mpdf> obs0, int n0, RESAMPLING_METHOD rm = SYSTEMATIC ) {
309                pf->set_model ( par0, obs0); 
310                pf->set_parameters(n0, rm );
[283]311                BMs.set_length ( n0 );
312        }
[660]313        //! set a prototype of BM, copy it to as many times as there is particles in pf
[638]314        void set_BM ( const BM &BMcond0 ) {
[32]315
[638]316                int n=pf->__w().length();
317                BMs.set_length(n);
[283]318                // copy
[638]319                //BMcond0 .condition ( pf->posterior()._sample ( 0 ) );
[477]320                for ( int i = 0; i < n; i++ ) {
[638]321                        BMs ( i ) = BMcond0._copy_();
[477]322                }
[32]323        };
324
[679]325        void bayes ( const vec &yt, const vec &cond );
[477]326        const epdf& posterior() const {
327                return jest;
328        }
[638]329        //! Extends options understood by BM::set_options by option
330        //! \li logmeans - meaning
[283]331        void set_options ( const string &opt ) {
[638]332                BM::set_options(opt);
[32]333        }
[283]334
[225]335        //!Access function
[536]336        const BM* _BM ( int i ) {
[477]337                return BMs ( i );
338        }
[638]339       
340        /*! configuration structure for basic PF
341        \code
342        BM              = BM_class;           // Bayesian filtr for analytical part of the model
343        parameter_pdf   = mpdf_class;         // transitional pdf for non-parametric part of the model
344        prior           = epdf_class;         // prior probability density
345        --- optional ---
346        n               = 10;                 // number of particles
347        resmethod       = 'systematic', or 'multinomial', or 'stratified'
348                                                                                  // resampling method
349        \endcode
350        */     
351        void from_setting(const Setting &set){
352                shared_ptr<mpdf> par = UI::build<mpdf>(set,"parameter_pdf",UI::compulsory);
353                shared_ptr<mpdf> obs= new mpdf(); // not used!!
[8]354
[638]355                pf = new PF;
[679]356                // prior must be set before BM
[638]357                pf->prior_from_set(set);
358                pf->resmethod_from_set(set);
359                pf->set_model(par,obs);
[679]360                               
[638]361                shared_ptr<BM> BM0 =UI::build<BM>(set,"BM",UI::compulsory);
362                set_BM(*BM0);
363               
364                string opt;
365                if (UI::get(opt,set,"options",UI::optional)){
366                        set_options(opt);
367                }
368                //set drv
369                //find potential input - what remains in rvc when we subtract rv
370                RV u = par->_rvc().remove_time().subt( par->_rv() );           
[679]371                set_yrv(concat(BM0->_yrv(),u) );
[638]372                validate();
[32]373        }
[638]374        void validate(){
375                try{
376                pf->validate();
377                } catch (std::exception &e){
378                        throw UIException("Error in PF part of MPF:");
379                }
380                jest.read_parameters();
[679]381                this2bm.set_connection(BMs(0)->_yrv(), BMs(0)->_rvc(), yrv, rvc);
382                this2bm.set_connection(pf->_yrv(), pf->_rvc(), yrv, rvc);
[32]383        }
[675]384
[638]385};
386UIREGISTER(MPF);
[32]387
388}
[8]389#endif // KF_H
390
Note: See TracBrowser for help on using the browser.