root/library/bdm/estim/mixtures.h @ 1014

Revision 1014, 5.8 kB (checked in by smidl, 14 years ago)

Mixtures example

  • Property svn:eol-style set to native
Line 
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
13#ifndef MIXTURES_H
14#define MIXTURES_H
15
16
17#include "../math/functions.h"
18#include "../stat/exp_family.h"
19#include "../stat/emix.h"
20#include "arx.h"
21
22namespace bdm {
23
24//! enum switch for internal approximation used in MixEF
25enum MixEF_METHOD { EM = 0, QB = 1};
26
27/*!
28* \brief Mixture of Exponential Family Densities
29
30An approximate estimation method for models with latent discrete variable, such as
31mixture models of the following kind:
32\f[
33f(y_t|\psi_t, \Theta) = \sum_{i=1}^{n} w_i f(y_t|\psi_t, \theta_i)
34\f]
35where  \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
37The 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
39This 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.
40
41Two methods are provided:
42 - QB where the probability of being from one component is computed using predictors,
43 - EM where the data is assigned to component with the highest likelihood (winner takes all)
44
45These methods are stored in attribute options:
46 - method: ["EM","QB"] estimation method as mentioned above, QB is default
47 - max_niter: maximum of iterations in bayes_batch()
48
49*/
50class MixEF: public BMEF {
51protected:
52        //! Models for Components of \f$\theta_i\f$
53        Array<BMEF*> Coms;
54        //! Statistics for weights
55        multiBM weights;
56        //aux
57        friend class eprod_mix;
58        //!Posterior on component parameters
59        class eprod_mix: public eprod_base {
60                protected:
61                const MixEF &mix; // pointer to parent.n
62                public:
63                eprod_mix(const MixEF &m):mix(m){}
64                const epdf* factor(int i) const {return (i==(mix.Coms.length()-1)) ? &mix.weights.posterior() : &mix.Coms(i)->posterior();}
65                const int no_factors()const {return mix.Coms.length()+1;}
66        } est;
67        ////!indices of component rvc in common rvc
68
69        class MixEF_options: public root{
70                public:
71                //! Flag for a method that is used in the inference
72                MixEF_METHOD method;
73
74                //! maximum number of iterations
75                int max_niter;
76       
77        MixEF_options():method(QB),max_niter(10){};
78               
79                void from_setting(const Setting &set){
80                        string meth;
81                        UI::get(meth,set,"method",UI::optional);
82                        if (meth=="EM") {method=EM;}
83                        max_niter =10;
84                        UI::get(max_niter,set,"max_niter",UI::optional);
85                };
86                void to_setting(Setting &set)const{
87                        string meth=(method==EM ? "EM" : "QB");
88                        UI::save(meth,set,"method");
89                        UI::save(max_niter,set,"max_niter");
90                };
91        };
92       
93        MixEF_options options;
94public:
95        //! Full constructor
96        MixEF ( const Array<BMEF*> &Coms0, const vec &alpha0 ) :
97                        BMEF ( ), Coms ( Coms0.length() ),
98                        weights (), est(*this), options() {
99                for ( int i = 0; i < Coms0.length(); i++ ) {
100                        Coms ( i ) = ( BMEF* ) Coms0 ( i )->_copy();
101                }
102                weights.set_parameters(alpha0);
103                weights.validate();
104        }
105
106        //! Constructor of empty mixture
107        MixEF () :
108                        BMEF ( ), Coms ( 0 ),
109                        weights (), est(*this), options() {
110        }
111        //! Copy constructor
112        MixEF ( const MixEF &M2 ) : BMEF ( ),  Coms ( M2.Coms.length() ),
113                        weights ( M2.weights ), est(*this), options(M2.options) {
114                for ( int i = 0; i < M2.Coms.length(); i++ ) {
115                        Coms ( i ) = (BMEF*) M2.Coms ( i )->_copy();
116                }
117        }
118
119        //! Initializing the mixture by a random pick of centroids from data
120        //! \param Com0 Initial component - necessary to determine its type.
121        //! \param Data Data on which the initialization will be done
122        //! \param c Initial number of components, default=5
123        //! when the number of data records (columns of Data) is equal to the number of requested components, each data is used, otherwise, they are picked randomly.
124        void init ( BMEF* Com0, const mat &Data, const int c = 5 );
125        //Destructor
126        //! Recursive EM-like algorithm (QB-variant), see Karny et. al, 2006
127        void bayes ( const vec &yt, const vec &cond );
128        //! batch weighted Bayes rule
129        double bayes_batch_weighted ( const mat &yt, const mat &cond, const vec &wData );
130        double bayes_batch ( const mat &yt, const mat &cond){
131                return bayes_batch_weighted(yt,cond,ones(yt.cols()));
132        };
133        double logpred ( const vec &yt, const vec &cond ) const;
134        //! return correctly typed posterior (covariant return)
135        const eprod_mix& posterior() const {
136                return est;
137        }
138
139        emix* epredictor(const vec &cond=vec()) const;
140        //! Flatten the density as if it was not estimated from the data
141        void flatten ( const BMEF* M2, double weight );
142        //! Access function
143        BMEF* _Coms ( int i ) {
144                return Coms ( i );
145        }
146
147        //!Set which method is to be used
148        void set_method ( MixEF_METHOD M ) {
149                options.method = M;
150        }
151
152void to_setting ( Setting &set ) const {
153        BMEF::to_setting( set );
154        UI::save ( Coms, set, "Coms" );
155        UI::save ( &weights, set, "weights" );
156        UI::save (options, set, "options");
157}
158/*! \brief reads data from setting
159*/
160void from_setting (const  Setting &set ) {
161        BMEF::from_setting( set );
162        UI::get ( Coms, set, "Coms" );
163        UI::get ( weights, set, "weights" );
164        UI::get (options, set, "options",UI::optional);
165}
166};
167UIREGISTER ( MixEF );
168
169class ARXprod: public ProdBMBase {
170        Array<shared_ptr<ARX> > arxs;
171        public:
172                ARX* bm(int i){return arxs(i).get();}
173                int no_bms() {return arxs.length();}
174};
175UIREGISTER(ARXprod);
176
177}
178#endif // MIXTURES_H
Note: See TracBrowser for help on using the browser.