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 | | //! Settings for MixEF |
80 | | /*! |
81 | | \code |
82 | | method = "EM"; % or QB (default) |
83 | | max_iter = 10; % maximum number of iterations |
84 | | \endcode |
85 | | */ |
86 | | void from_setting(const Setting &set){ |
87 | | string meth; |
88 | | UI::get(meth,set,"method",UI::optional); |
89 | | if (meth=="EM") {method=EM;} |
90 | | max_niter =10; |
91 | | UI::get(max_niter,set,"max_niter",UI::optional); |
92 | | }; |
93 | | void to_setting(Setting &set)const{ |
94 | | string meth=(method==EM ? "EM" : "QB"); |
95 | | UI::save(meth,set,"method"); |
96 | | UI::save(max_niter,set,"max_niter"); |
97 | | }; |
98 | | }; |
99 | | |
100 | | MixEF_options options; |
| 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 { |
| 65 | return (i==(mix.Coms.length()-1)) ? &mix.weights.posterior() : &mix.Coms(i)->posterior(); |
| 66 | } |
| 67 | const int no_factors()const { |
| 68 | return mix.Coms.length()+1; |
| 69 | } |
| 70 | } est; |
| 71 | ////!indices of component rvc in common rvc |
| 72 | |
| 73 | class MixEF_options: public root { |
| 74 | public: |
| 75 | //! Flag for a method that is used in the inference |
| 76 | MixEF_METHOD method; |
| 77 | |
| 78 | //! maximum number of iterations |
| 79 | int max_niter; |
| 80 | |
| 81 | MixEF_options():method(QB),max_niter(10) {}; |
| 82 | |
| 83 | //! Settings for MixEF |
| 84 | /*! |
| 85 | \code |
| 86 | method = "EM"; % or QB (default) |
| 87 | max_iter = 10; % maximum number of iterations |
| 88 | \endcode |
| 89 | */ |
| 90 | void from_setting(const Setting &set) { |
| 91 | string meth; |
| 92 | UI::get(meth,set,"method",UI::optional); |
| 93 | if (meth=="EM") { |
| 94 | method=EM; |
| 95 | } |
| 96 | max_niter =10; |
| 97 | UI::get(max_niter,set,"max_niter",UI::optional); |
| 98 | }; |
| 99 | void to_setting(Setting &set)const { |
| 100 | string meth=(method==EM ? "EM" : "QB"); |
| 101 | UI::save(meth,set,"method"); |
| 102 | UI::save(max_niter,set,"max_niter"); |
| 103 | }; |
| 104 | }; |
| 105 | |
| 106 | MixEF_options options; |
102 | | //! Full constructor |
103 | | MixEF ( const Array<BMEF*> &Coms0, const vec &alpha0 ) : |
104 | | BMEF ( ), Coms ( Coms0.length() ), |
105 | | weights (), est(*this), options() { |
106 | | for ( int i = 0; i < Coms0.length(); i++ ) { |
107 | | Coms ( i ) = ( BMEF* ) Coms0 ( i )->_copy(); |
108 | | } |
109 | | weights.set_parameters(alpha0); |
110 | | weights.validate(); |
111 | | } |
112 | | |
113 | | //! Constructor of empty mixture |
114 | | MixEF () : |
115 | | BMEF ( ), Coms ( 0 ), |
116 | | weights (), est(*this), options() { |
117 | | } |
118 | | //! Copy constructor |
119 | | MixEF ( const MixEF &M2 ) : BMEF ( ), Coms ( M2.Coms.length() ), |
120 | | weights ( M2.weights ), est(*this), options(M2.options) { |
121 | | for ( int i = 0; i < M2.Coms.length(); i++ ) { |
122 | | Coms ( i ) = (BMEF*) M2.Coms ( i )->_copy(); |
123 | | } |
124 | | } |
125 | | |
126 | | //! Initializing the mixture by a random pick of centroids from data |
127 | | //! \param Com0 Initial component - necessary to determine its type. |
128 | | //! \param Data Data on which the initialization will be done |
129 | | //! \param c Initial number of components, default=5 |
130 | | //! 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. |
131 | | void init ( BMEF* Com0, const mat &Data, const int c = 5 ); |
132 | | //Destructor |
133 | | //! Recursive EM-like algorithm (QB-variant), see Karny et. al, 2006 |
134 | | void bayes ( const vec &yt, const vec &cond ); |
135 | | //! batch weighted Bayes rule |
136 | | double bayes_batch_weighted ( const mat &yt, const mat &cond, const vec &wData ); |
137 | | double bayes_batch ( const mat &yt, const mat &cond){ |
138 | | return bayes_batch_weighted(yt,cond,ones(yt.cols())); |
139 | | }; |
140 | | double logpred ( const vec &yt, const vec &cond ) const; |
141 | | //! return correctly typed posterior (covariant return) |
142 | | const eprod_mix& posterior() const { |
143 | | return est; |
144 | | } |
145 | | |
146 | | emix* epredictor(const vec &cond=vec()) const; |
147 | | //! Flatten the density as if it was not estimated from the data |
148 | | void flatten ( const BMEF* M2, double weight ); |
149 | | //! Access function |
150 | | BMEF* _Coms ( int i ) { |
151 | | return Coms ( i ); |
152 | | } |
153 | | |
154 | | //!Set which method is to be used |
155 | | void set_method ( MixEF_METHOD M ) { |
156 | | options.method = M; |
157 | | } |
158 | | |
159 | | void to_setting ( Setting &set ) const { |
160 | | BMEF::to_setting( set ); |
161 | | UI::save ( Coms, set, "Coms" ); |
162 | | UI::save ( &weights, set, "weights" ); |
163 | | UI::save (options, set, "options"); |
164 | | } |
165 | | /*! \brief reads data from setting |
166 | | \code |
167 | | Coms = {struct('class',"BMEF..."),...}; % Components - Bayesian models (BM) |
168 | | weights = [0.2, 0.3,...]; % weights |
169 | | options.method = "EM" or "QB"; % methods of computing bayes |
170 | | options.max_iter = 10; % maximum number of iterations in bayes_batch |
171 | | \endcode |
172 | | */ |
173 | | void from_setting (const Setting &set ) { |
174 | | BMEF::from_setting( set ); |
175 | | UI::get ( Coms, set, "Coms" ); |
176 | | UI::get ( weights, set, "weights" ); |
177 | | UI::get (options, set, "options",UI::optional); |
178 | | } |
| 108 | //! Full constructor |
| 109 | MixEF ( const Array<BMEF*> &Coms0, const vec &alpha0 ) : |
| 110 | BMEF ( ), Coms ( Coms0.length() ), |
| 111 | weights (), est(*this), options() { |
| 112 | for ( int i = 0; i < Coms0.length(); i++ ) { |
| 113 | Coms ( i ) = ( BMEF* ) Coms0 ( i )->_copy(); |
| 114 | } |
| 115 | weights.set_parameters(alpha0); |
| 116 | weights.validate(); |
| 117 | } |
| 118 | |
| 119 | //! Constructor of empty mixture |
| 120 | MixEF () : |
| 121 | BMEF ( ), Coms ( 0 ), |
| 122 | weights (), est(*this), options() { |
| 123 | } |
| 124 | //! Copy constructor |
| 125 | MixEF ( const MixEF &M2 ) : BMEF ( ), Coms ( M2.Coms.length() ), |
| 126 | weights ( M2.weights ), est(*this), options(M2.options) { |
| 127 | for ( int i = 0; i < M2.Coms.length(); i++ ) { |
| 128 | Coms ( i ) = (BMEF*) M2.Coms ( i )->_copy(); |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | //! Initializing the mixture by a random pick of centroids from data |
| 133 | //! \param Com0 Initial component - necessary to determine its type. |
| 134 | //! \param Data Data on which the initialization will be done |
| 135 | //! \param c Initial number of components, default=5 |
| 136 | //! 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. |
| 137 | void init ( BMEF* Com0, const mat &Data, const int c = 5 ); |
| 138 | //Destructor |
| 139 | //! Recursive EM-like algorithm (QB-variant), see Karny et. al, 2006 |
| 140 | void bayes ( const vec &yt, const vec &cond ); |
| 141 | //! batch weighted Bayes rule |
| 142 | double bayes_batch_weighted ( const mat &yt, const mat &cond, const vec &wData ); |
| 143 | double bayes_batch ( const mat &yt, const mat &cond) { |
| 144 | return bayes_batch_weighted(yt,cond,ones(yt.cols())); |
| 145 | }; |
| 146 | double logpred ( const vec &yt, const vec &cond ) const; |
| 147 | //! return correctly typed posterior (covariant return) |
| 148 | const eprod_mix& posterior() const { |
| 149 | return est; |
| 150 | } |
| 151 | |
| 152 | emix* epredictor(const vec &cond=vec()) const; |
| 153 | //! Flatten the density as if it was not estimated from the data |
| 154 | void flatten ( const BMEF* M2, double weight ); |
| 155 | //! Access function |
| 156 | BMEF* _Coms ( int i ) { |
| 157 | return Coms ( i ); |
| 158 | } |
| 159 | |
| 160 | //!Set which method is to be used |
| 161 | void set_method ( MixEF_METHOD M ) { |
| 162 | options.method = M; |
| 163 | } |
| 164 | |
| 165 | void to_setting ( Setting &set ) const { |
| 166 | BMEF::to_setting( set ); |
| 167 | UI::save ( Coms, set, "Coms" ); |
| 168 | UI::save ( &weights, set, "weights" ); |
| 169 | UI::save (options, set, "options"); |
| 170 | } |
| 171 | /*! \brief reads data from setting |
| 172 | \code |
| 173 | Coms = {struct('class',"BMEF..."),...}; % Components - Bayesian models (BM) |
| 174 | weights = [0.2, 0.3,...]; % weights |
| 175 | options.method = "EM" or "QB"; % methods of computing bayes |
| 176 | options.max_iter = 10; % maximum number of iterations in bayes_batch |
| 177 | \endcode |
| 178 | */ |
| 179 | void from_setting (const Setting &set ) { |
| 180 | BMEF::from_setting( set ); |
| 181 | UI::get ( Coms, set, "Coms" ); |
| 182 | UI::get ( weights, set, "weights" ); |
| 183 | UI::get (options, set, "options",UI::optional); |
| 184 | } |