[176] | 1 | /*! |
---|
| 2 | \file |
---|
| 3 | \brief Bayesian Filtering for mixtures of exponential family (EF) members |
---|
| 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 | |
---|
[394] | 13 | #ifndef MIXTURES_H |
---|
| 14 | #define MIXTURES_H |
---|
[176] | 15 | |
---|
[262] | 16 | |
---|
[384] | 17 | #include "../math/functions.h" |
---|
| 18 | #include "../stat/exp_family.h" |
---|
[394] | 19 | #include "../stat/emix.h" |
---|
[997] | 20 | #include "arx.h" |
---|
[176] | 21 | |
---|
[286] | 22 | namespace bdm { |
---|
[176] | 23 | |
---|
[536] | 24 | //! enum switch for internal approximation used in MixEF |
---|
[189] | 25 | enum MixEF_METHOD { EM = 0, QB = 1}; |
---|
| 26 | |
---|
[176] | 27 | /*! |
---|
| 28 | * \brief Mixture of Exponential Family Densities |
---|
| 29 | |
---|
| 30 | An approximate estimation method for models with latent discrete variable, such as |
---|
| 31 | mixture models of the following kind: |
---|
| 32 | \f[ |
---|
| 33 | f(y_t|\psi_t, \Theta) = \sum_{i=1}^{n} w_i f(y_t|\psi_t, \theta_i) |
---|
| 34 | \f] |
---|
| 35 | where \f$\psi\f$ is a known function of past outputs, \f$w=[w_1,\ldots,w_n]\f$ are component weights, and component parameters \f$\theta_i\f$ are assumed to be mutually independent. \f$\Theta\f$ is an aggregation af all component parameters and weights, i.e. \f$\Theta = [\theta_1,\ldots,\theta_n,w]\f$. |
---|
| 36 | |
---|
| 37 | The characteristic feature of this model is that if the exact values of the latent variable were known, estimation of the parameters can be handled by a single model. For example, for the case of mixture models, posterior density for each component parameters would be a BayesianModel from Exponential Family. |
---|
| 38 | |
---|
[180] | 39 | This class uses EM-style type algorithms for estimation of its parameters. Under this simplification, the posterior density is a product of exponential family members, hence under EM-style approximate estimation this class itself belongs to the exponential family. |
---|
[176] | 40 | |
---|
| 41 | TODO: Extend BM to use rvc. |
---|
| 42 | */ |
---|
[197] | 43 | class MixEF: public BMEF { |
---|
[176] | 44 | protected: |
---|
| 45 | //!Number of components |
---|
| 46 | int n; |
---|
| 47 | //! Models for Components of \f$\theta_i\f$ |
---|
| 48 | Array<BMEF*> Coms; |
---|
| 49 | //! Statistics for weights |
---|
| 50 | multiBM weights; |
---|
[886] | 51 | //aux |
---|
| 52 | friend class eprod_mix; |
---|
[176] | 53 | //!Posterior on component parameters |
---|
[886] | 54 | class eprod_mix: public eprod_base { |
---|
| 55 | protected: |
---|
| 56 | const MixEF &mix; // pointer to parent.n |
---|
| 57 | public: |
---|
| 58 | eprod_mix(const MixEF &m):mix(m){} |
---|
| 59 | const epdf* factor(int i) const {return (i==(mix.n-1)) ? &mix.weights.posterior() : &mix.Coms(i)->posterior();} |
---|
| 60 | const int no_factors()const {return mix.n+1;} |
---|
| 61 | } est; |
---|
[897] | 62 | ////!indices of component rvc in common rvc |
---|
[286] | 63 | |
---|
[189] | 64 | //! Flag for a method that is used in the inference |
---|
| 65 | MixEF_METHOD method; |
---|
[286] | 66 | |
---|
[176] | 67 | public: |
---|
| 68 | //! Full constructor |
---|
| 69 | MixEF ( const Array<BMEF*> &Coms0, const vec &alpha0 ) : |
---|
[286] | 70 | BMEF ( ), n ( Coms0.length() ), Coms ( n ), |
---|
[886] | 71 | weights (), est(*this), method ( QB ) { |
---|
[477] | 72 | for ( int i = 0; i < n; i++ ) { |
---|
[766] | 73 | Coms ( i ) = ( BMEF* ) Coms0 ( i )->_copy(); |
---|
[477] | 74 | } |
---|
[741] | 75 | weights.set_parameters(alpha0); |
---|
| 76 | weights.validate(); |
---|
[565] | 77 | } |
---|
| 78 | |
---|
[197] | 79 | //! Constructor of empty mixture |
---|
[176] | 80 | MixEF () : |
---|
[270] | 81 | BMEF ( ), n ( 0 ), Coms ( 0 ), |
---|
[886] | 82 | weights (), est(*this), method ( QB ) { |
---|
[477] | 83 | } |
---|
[197] | 84 | //! Copy constructor |
---|
[286] | 85 | MixEF ( const MixEF &M2 ) : BMEF ( ), n ( M2.n ), Coms ( n ), |
---|
[886] | 86 | weights ( M2.weights ), est(*this), method ( M2.method ) { |
---|
[477] | 87 | for ( int i = 0; i < n; i++ ) { |
---|
[766] | 88 | Coms ( i ) = (BMEF*) M2.Coms ( i )->_copy(); |
---|
[477] | 89 | } |
---|
[286] | 90 | } |
---|
[565] | 91 | |
---|
[176] | 92 | //! Initializing the mixture by a random pick of centroids from data |
---|
| 93 | //! \param Com0 Initial component - necessary to determine its type. |
---|
| 94 | //! \param Data Data on which the initialization will be done |
---|
| 95 | //! \param c Initial number of components, default=5 |
---|
[735] | 96 | void init ( BMEF* Com0, const mat &Data, const int c = 5 ); |
---|
[176] | 97 | //Destructor |
---|
| 98 | //! Recursive EM-like algorithm (QB-variant), see Karny et. al, 2006 |
---|
[679] | 99 | void bayes ( const vec &yt, const vec &cond ); |
---|
[176] | 100 | //! EM algorithm |
---|
[679] | 101 | void bayes ( const mat &yt, const vec &cond ); |
---|
[737] | 102 | //! batch weighted Bayes rule |
---|
[682] | 103 | void bayes_batch ( const mat &yt, const mat &cond, const vec &wData ); |
---|
[679] | 104 | double logpred ( const vec &yt ) const; |
---|
[660] | 105 | //! return correctly typed posterior (covariant return) |
---|
[886] | 106 | const eprod_mix& posterior() const { |
---|
| 107 | return est; |
---|
[477] | 108 | } |
---|
[746] | 109 | |
---|
[943] | 110 | emix* epredictor(const vec &cond=vec()) const; |
---|
[180] | 111 | //! Flatten the density as if it was not estimated from the data |
---|
[286] | 112 | void flatten ( const BMEF* M2 ); |
---|
[193] | 113 | //! Access function |
---|
[477] | 114 | BMEF* _Coms ( int i ) { |
---|
| 115 | return Coms ( i ); |
---|
| 116 | } |
---|
[286] | 117 | |
---|
[189] | 118 | //!Set which method is to be used |
---|
[477] | 119 | void set_method ( MixEF_METHOD M ) { |
---|
| 120 | method = M; |
---|
| 121 | } |
---|
[737] | 122 | |
---|
| 123 | void to_setting ( Setting &set ) const { |
---|
[746] | 124 | BMEF::to_setting( set ); |
---|
[737] | 125 | UI::save ( Coms, set, "Coms" ); |
---|
[746] | 126 | UI::save ( &weights, set, "weights" ); |
---|
[735] | 127 | } |
---|
[176] | 128 | }; |
---|
[746] | 129 | UIREGISTER ( MixEF ); |
---|
[176] | 130 | |
---|
[997] | 131 | class ARXprod: public ProdBMBase { |
---|
| 132 | Array<shared_ptr<ARX> > arxs; |
---|
| 133 | public: |
---|
| 134 | ARX* bm(int i){return arxs(i).get();} |
---|
| 135 | int no_bms() {return arxs.length();} |
---|
| 136 | }; |
---|
| 137 | UIREGISTER(ARXprod); |
---|
| 138 | |
---|
[254] | 139 | } |
---|
[384] | 140 | #endif // MIXTURES_H |
---|