126 | | void egiwmix::set_parameters ( const vec &w0, const Array<egiw*> &Coms0, bool copy ) { |
127 | | w = w0 / sum ( w0 ); |
128 | | int i; |
129 | | for ( i = 0; i < w.length(); i++ ) { |
130 | | bdm_assert_debug ( dim == ( Coms0 ( i )->dimension() ), "Component sizes do not match!" ); |
131 | | } |
132 | | if ( copy ) { |
133 | | Coms.set_length ( Coms0.length() ); |
134 | | for ( i = 0; i < w.length(); i++ ) { |
135 | | bdm_error ( "Not implemented" ); |
136 | | // *Coms ( i ) = *Coms0 ( i ); |
137 | | } |
138 | | destroyComs = true; |
139 | | } else { |
140 | | Coms = Coms0; |
141 | | destroyComs = false; |
142 | | } |
143 | | } |
144 | | |
145 | | void egiwmix::validate (){ |
146 | | dim = Coms ( 0 )->dimension(); |
147 | | } |
148 | | |
149 | | vec egiwmix::sample() const { |
150 | | //Sample which component |
151 | | vec cumDist = cumsum ( w ); |
152 | | double u0; |
153 | | #pragma omp critical |
154 | | u0 = UniRNG.sample(); |
155 | | |
156 | | int i = 0; |
157 | | while ( ( cumDist ( i ) < u0 ) && ( i < ( w.length() - 1 ) ) ) { |
158 | | i++; |
159 | | } |
160 | | |
161 | | return Coms ( i )->sample(); |
162 | | } |
163 | | |
164 | | vec egiwmix::mean() const { |
165 | | int i; |
166 | | vec mu = zeros ( dim ); |
167 | | for ( i = 0; i < w.length(); i++ ) { |
168 | | mu += w ( i ) * Coms ( i )->mean(); |
169 | | } |
170 | | return mu; |
171 | | } |
172 | | |
173 | | vec egiwmix::variance() const { |
174 | | // non-central moment |
175 | | vec mom2 = zeros ( dim ); |
176 | | for ( int i = 0; i < w.length(); i++ ) { |
177 | | // pow is overloaded, we have to use another approach |
178 | | mom2 += w ( i ) * ( Coms ( i )->variance() + elem_mult ( Coms ( i )->mean(), Coms ( i )->mean() ) ); |
179 | | } |
180 | | // central moment |
181 | | // pow is overloaded, we have to use another approach |
182 | | return mom2 - elem_mult ( mean(), mean() ); |
183 | | } |
184 | | |
185 | | shared_ptr<epdf> egiwmix::marginal ( const RV &rv ) const { |
186 | | emix *tmp = new emix(); |
187 | | shared_ptr<epdf> narrow ( tmp ); |
188 | | marginal ( rv, *tmp ); |
189 | | return narrow; |
190 | | } |
191 | | |
192 | | void egiwmix::marginal ( const RV &rv, emix &target ) const { |
193 | | bdm_assert_debug ( isnamed(), "rvs are not assigned" ); |
194 | | |
195 | | Array<shared_ptr<epdf> > Cn ( Coms.length() ); |
196 | | for ( int i = 0; i < Coms.length(); i++ ) { |
197 | | Cn ( i ) = Coms ( i )->marginal ( rv ); |
198 | | } |
199 | | |
200 | | target._w() = w; |
201 | | target._Coms() = Cn; |
202 | | target.validate(); |
203 | | } |
204 | | |
205 | | egiw* egiwmix::approx() { |
206 | | // NB: dimx == 1 !!! |
207 | | // The following code might look a bit spaghetti-like, |
208 | | // consult Dedecius, K. et al.: Partial forgetting in AR models. |
209 | | |
210 | | double sumVecCommon; // common part for many terms in eq. |
211 | | int len = w.length(); // no. of mix components |
212 | | int dimLS = Coms ( 1 )->_V()._D().length() - 1; // dim of LS |
213 | | vec vecNu ( len ); // vector of dfms of components |
214 | | vec vecD ( len ); // vector of LS reminders of comps. |
215 | | vec vecCommon ( len ); // vector of common parts |
216 | | mat matVecsTheta; // matrix which rows are theta vects. |
217 | | |
218 | | // fill in the vectors vecNu, vecD and matVecsTheta |
219 | | for ( int i = 0; i < len; i++ ) { |
220 | | vecNu.shift_left ( Coms ( i )->_nu() ); |
221 | | vecD.shift_left ( Coms ( i )->_V()._D() ( 0 ) ); |
222 | | matVecsTheta.append_row ( Coms ( i )->est_theta() ); |
223 | | } |
224 | | |
225 | | // calculate the common parts and their sum |
226 | | vecCommon = elem_mult ( w, elem_div ( vecNu, vecD ) ); |
227 | | sumVecCommon = sum ( vecCommon ); |
228 | | |
229 | | // LS estimator of theta |
230 | | vec aprEstTheta ( dimLS ); |
231 | | aprEstTheta.zeros(); |
232 | | for ( int i = 0; i < len; i++ ) { |
233 | | aprEstTheta += matVecsTheta.get_row ( i ) * vecCommon ( i ); |
234 | | } |
235 | | aprEstTheta /= sumVecCommon; |
236 | | |
237 | | |
238 | | // LS estimator of dfm |
239 | | double aprNu; |
240 | | double A = log ( sumVecCommon ); // Term 'A' in equation |
241 | | |
242 | | for ( int i = 0; i < len; i++ ) { |
243 | | A += w ( i ) * ( log ( vecD ( i ) ) - psi ( 0.5 * vecNu ( i ) ) ); |
244 | | } |
245 | | |
246 | | aprNu = ( 1 + sqrt ( 1 + 2 * ( A - LOG2 ) / 3 ) ) / ( 2 * ( A - LOG2 ) ); |
247 | | |
248 | | |
249 | | // LS reminder (term D(0,0) in C-syntax) |
250 | | double aprD = aprNu / sumVecCommon; |
251 | | |
252 | | // Aproximation of cov |
253 | | // the following code is very numerically sensitive, thus |
254 | | // we have to eliminate decompositions etc. as much as possible |
255 | | mat aprC = zeros ( dimLS, dimLS ); |
256 | | for ( int i = 0; i < len; i++ ) { |
257 | | aprC += Coms ( i )->est_theta_cov().to_mat() * w ( i ); |
258 | | vec tmp = ( matVecsTheta.get_row ( i ) - aprEstTheta ); |
259 | | aprC += vecCommon ( i ) * outer_product ( tmp, tmp ); |
260 | | } |
261 | | |
262 | | // Construct GiW pdf :: BEGIN |
263 | | ldmat aprCinv ( inv ( aprC ) ); |
264 | | vec D = concat ( aprD, aprCinv._D() ); |
265 | | mat L = eye ( dimLS + 1 ); |
266 | | L.set_submatrix ( 1, 0, aprCinv._L() * aprEstTheta ); |
267 | | L.set_submatrix ( 1, 1, aprCinv._L() ); |
268 | | ldmat aprLD ( L, D ); |
269 | | |
270 | | egiw* aprgiw = new egiw ( 1, aprLD, aprNu ); |
271 | | return aprgiw; |
272 | | }; |
| 117 | void emix::from_setting ( const Setting &set ) { |
| 118 | UI::get ( Coms, set, "pdfs", UI::compulsory ); |
| 119 | UI::get ( w, set, "weights", UI::compulsory ); |
| 120 | } |
| 121 | |
| 122 | void emix::validate (){ |
| 123 | emix_base::validate(); |
| 124 | dim = Coms ( 0 )->dimension(); |
| 125 | } |
| 126 | |
407 | | for ( int i = 0; i < epdfs.length(); i++ ) { |
408 | | tmp += epdfs ( i )->evallog ( dls ( i )->pushdown ( val ) ); |
409 | | } |
410 | | bdm_assert_debug ( std::isfinite ( tmp ), "Infinite" ); |
411 | | return tmp; |
412 | | } |
413 | | |
414 | | } |
415 | | // mprod::mprod ( Array<pdf*> mFacs, bool overlap) : pdf ( RV(), RV() ), n ( mFacs.length() ), epdfs ( n ), pdfs ( mFacs ), rvinds ( n ), rvcinrv ( n ), irvcs_rvc ( n ) { |
416 | | // int i; |
417 | | // bool rvaddok; |
418 | | // // Create rv |
419 | | // for ( i = 0;i < n;i++ ) { |
420 | | // rvaddok=rv.add ( pdfs ( i )->_rv() ); //add rv to common rvs. |
421 | | // // If rvaddok==false, pdfs overlap => assert error. |
422 | | // epdfs ( i ) = & ( pdfs ( i )->posterior() ); // add pointer to epdf |
423 | | // }; |
424 | | // // Create rvc |
425 | | // for ( i = 0;i < n;i++ ) { |
426 | | // rvc.add ( pdfs ( i )->_rvc().subt ( rv ) ); //add rv to common rvs. |
427 | | // }; |
428 | | // |
429 | | // // independent = true; |
430 | | // //test rvc of pdfs and fill rvinds |
431 | | // for ( i = 0;i < n;i++ ) { |
432 | | // // find ith rv in common rv |
433 | | // rvsinrv ( i ) = pdfs ( i )->_rv().dataind ( rv ); |
434 | | // // find ith rvc in common rv |
435 | | // rvcinrv ( i ) = pdfs ( i )->_rvc().dataind ( rv ); |
436 | | // // find ith rvc in common rv |
437 | | // irvcs_rvc ( i ) = pdfs ( i )->_rvc().dataind ( rvc ); |
438 | | // // |
439 | | // /* if ( rvcinrv ( i ).length() >0 ) {independent = false;} |
440 | | // if ( irvcs_rvc ( i ).length() >0 ) {independent = false;}*/ |
441 | | // } |
442 | | // }; |
443 | | |
| 261 | for ( int i = 0; i < no_factors(); i++ ) { |
| 262 | tmp += factor ( i )->evallog ( dls ( i )->pushdown ( val ) ); |
| 263 | } |
| 264 | //bdm_assert_debug ( std::isfinite ( tmp ), "Infinite" ); |
| 265 | return tmp; |
| 266 | } |
| 267 | |
| 268 | } |
| 269 | |