root/library/bdm/estim/arx.cpp @ 1187

Revision 1176, 14.1 kB (checked in by smidl, 14 years ago)

student epredictor in ARX

  • Property svn:eol-style set to native
Line 
1#include "arx.h"
2namespace bdm {
3
4void ARX::bayes_weighted ( const vec &yt, const vec &cond, const double w ) {
5    bdm_assert_debug ( yt.length() == dimy, "BM::bayes yt is of size "+num2str(yt.length())+" expected dimension is "+num2str(dimy) );
6    bdm_assert_debug ( cond.length() == rgrlen , "BM::bayes cond is of size "+num2str(cond.length())+" expected dimension is "+num2str(rgrlen) );
7
8    BMEF::bayes_weighted(yt,cond,w); //potential discount scheduling
9    double lnc;
10    //cache
11    ldmat &V = est._V();
12    double &nu = est._nu();
13
14    dyad.set_subvector ( 0, yt );
15    if (cond.length()>0)
16        dyad.set_subvector ( dimy, cond );
17    // possible "1" is there from the beginning
18
19    if ( frg < 1.0 ) {
20        est.pow ( frg ); // multiply V and nu
21
22
23        //stabilize
24        ldmat V0 = alter_est._V(); //$ copy
25        double &nu0 = alter_est._nu();
26
27        V0 *= ( 1 - frg );
28        V += V0; //stabilization
29        nu += ( 1 - frg ) * nu0;
30
31        // recompute loglikelihood of new "prior"
32        if ( evalll ) {
33            last_lognc = est.lognc();
34        }
35    }
36    V.opupdt ( dyad, w );
37    nu += w;
38
39    // log(sqrt(2*pi)) = 0.91893853320467
40    if ( evalll ) {
41        lnc = est.lognc();
42        ll = lnc - last_lognc - 0.91893853320467;
43        last_lognc = lnc;
44    }
45}
46
47double ARX::logpred ( const vec &yt, const vec &cond ) const {
48    egiw pred ( est );
49    ldmat &V = pred._V();
50    double &nu = pred._nu();
51
52    double lll;
53    vec dyad_p = dyad;
54    dyad_p.set_subvector ( 0, yt );
55    dyad_p.set_subvector(dimy,cond);
56
57    if ( frg < 1.0 ) {
58        pred.pow ( frg );
59        lll = pred.lognc();
60    } else//should be save: last_lognc is changed only by bayes;
61        if ( evalll ) {
62            lll = last_lognc;
63        } else {
64            lll = pred.lognc();
65        }
66
67    V.opupdt ( dyad_p, 1.0 );
68    nu += 1.0;
69    // log(sqrt(2*pi)) = 0.91893853320467
70    return pred.lognc() - lll - 0.91893853320467;
71}
72
73vec ARX::samplepred(const vec &cond) const{
74        mat M;
75        chmat R;
76        est.sample_mat(M,R);
77       
78        vec tmp;
79        if (dimc>0){
80                if (have_constant){
81                        tmp = M*concat(cond,1.0);
82                } else {
83                        tmp = M*cond;
84                }
85        } else {
86                tmp = zeros(dimy);
87        }
88        tmp += R._Ch().T()*randn(dimy);
89        return tmp;
90}
91
92void ARX::flatten ( const BMEF* B , double weight =1.0) {
93    const ARX* A = dynamic_cast<const ARX*> ( B );
94    // nu should be equal to B.nu
95    est.pow ( A->posterior()._nu() / posterior()._nu() *weight);
96    if ( evalll ) {
97        last_lognc = est.lognc();
98    }
99}
100
101ARX* ARX::_copy ( ) const {
102    ARX* Tmp = new ARX ( *this );
103    return Tmp;
104}
105
106void ARX::set_statistics ( const BMEF* B0 ) {
107    const ARX* A0 = dynamic_cast<const ARX*> ( B0 );
108
109    bdm_assert_debug ( dimension() == A0->dimension(), "Statistics of different dimensions" );
110    set_statistics ( A0->dimensiony(), A0->posterior()._V(), A0->posterior()._nu() );
111}
112
113enorm<ldmat>* ARX::epredictor ( const vec &cond ) const {
114    bdm_assert_debug ( cond.length() == rgrlen , "ARX::epredictor cond is of size "+num2str(cond.length())+" expected dimension is "+num2str(rgrlen) );
115
116    mat mu ( dimy, posterior()._V().rows() - dimy );
117    mat R ( dimy, dimy );
118
119    vec ext_rgr;
120    if (have_constant) {
121        ext_rgr = concat(cond,vec_1(1.0));
122    } else {
123        ext_rgr = cond;
124    }
125
126    enorm<ldmat>* tmp;
127    tmp = new enorm<ldmat> ( );
128    //TODO: too hackish
129    if ( yrv._dsize() > 0 ) {
130    }
131
132    est.mean_mat ( mu, R ); //mu =
133    //correction for student-t  -- TODO check if correct!!
134    R*=posterior()._nu()/(posterior()._nu()-2);
135    if (mu.cols()>0) {// nonempty egiw
136        mat p_mu = mu.T() * ext_rgr;    //the result is one column
137        tmp->set_parameters ( p_mu.get_col ( 0 ), ldmat ( R ) );
138    } else {
139        tmp->set_parameters ( zeros( R.rows() ), ldmat ( R ) );
140    }
141    if (dimy==yrv._dsize())
142        tmp->set_rv(yrv);
143    return tmp;
144}
145
146estudent<ldmat>* ARX::epredictor_student ( const vec &cond ) const {
147        bdm_assert_debug ( cond.length() == rgrlen , "ARX::epredictor cond is of size "+num2str(cond.length())+" expected dimension is "+num2str(rgrlen) );
148       
149        mat mu ( dimy, posterior()._V().rows() - dimy );
150       
151        vec ext_rgr;
152        if (have_constant) {
153                ext_rgr = concat(cond,vec_1(1.0));
154        } else {
155                ext_rgr = cond;
156        }
157       
158        estudent<ldmat>* tmp = new estudent<ldmat> ( );
159        //TODO: too hackish
160        if ( yrv._dsize() > 0 ) {
161        }
162
163        ldmat Lam;
164        ldmat Vz;
165
166        est.factorize( mu, Vz, Lam ); //mu =
167        //correction for student-t  -- TODO check if correct!!
168        double zeta =0;
169        if (mu.cols()>0) {// nonempty egiw
170                mat p_mu = mu.T() * ext_rgr;    //the result is one column
171                tmp->_mu()= p_mu.get_col ( 0 );
172                zeta = Vz.invqform(ext_rgr);
173        } else {
174                tmp->_mu()=zeros(dimy);
175        }
176        // nu-rgrlen+2+dimy = delta+dimy
177        tmp->_delta()=est._nu()+2-rgrlen;
178        tmp->_H()=Lam;
179        tmp->_H()*=1/tmp->_delta();
180        tmp->_H()*=(1+zeta);
181       
182        if (dimy==yrv._dsize())
183                tmp->set_rv(yrv);
184        return tmp;
185}
186
187mlstudent* ARX::predictor ( ) const {
188    const ldmat &V = posterior()._V();
189
190    mat mu ( dimy, V.rows() - dimy );
191    mat R ( dimy, dimy );
192    mlstudent* tmp;
193    tmp = new mlstudent ( );
194
195    est.mean_mat ( mu, R ); //
196    mu = mu.T();
197
198    int end = V._L().rows() - 1;
199    ldmat Lam ( V._L() ( dimy, end, dimy, end ), V._D() ( dimy, end ) );  //exp val of R
200
201
202    if ( have_constant ) { // no constant term
203        //Assume the constant term is the last one:
204        if ( mu.cols() > 1 ) {
205            tmp->set_parameters ( mu.get_cols ( 0, mu.cols() - 2 ), mu.get_col ( mu.cols() - 1 ), ldmat ( R ), Lam );
206        } else {
207            tmp->set_parameters ( mat ( dimy, dimc ), mu.get_col ( mu.cols() - 1 ), ldmat ( R ), Lam );
208        }
209    } else {
210        // no constant term
211        tmp->set_parameters ( mu, zeros ( dimy ), ldmat ( R ), Lam );
212    }
213    return tmp;
214}
215
216
217
218/*! \brief Return the best structure
219@param Eg a copy of GiW density that is being examined
220@param Eg0 a copy of prior GiW density before estimation
221@param Egll likelihood of the current Eg
222@param indices current indices
223\return best likelihood in the structure below the given one
224*/
225double egiw_bestbelow ( egiw Eg, egiw Eg0, double Egll, ivec &indices ) { //parameter Eg is a copy!
226    ldmat Vo = Eg._V(); //copy
227    ldmat Vo0 = Eg._V(); //copy
228    ldmat& Vp = Eg._V(); // pointer into Eg
229    ldmat& Vp0 = Eg._V(); // pointer into Eg
230    int end = Vp.rows() - 1;
231    int i;
232    mat Li;
233    mat Li0;
234    double maxll = Egll;
235    double tmpll = Egll;
236    double belll = Egll;
237
238    ivec tmpindices;
239    ivec maxindices = indices;
240
241
242    cout << "bb:(" << indices << ") ll=" << Egll << endl;
243
244    //try to remove only one rv
245    for ( i = 0; i < end; i++ ) {
246        //copy original
247        Li = Vo._L();
248        Li0 = Vo0._L();
249        //remove stuff
250        Li.del_col ( i + 1 );
251        Li0.del_col ( i + 1 );
252        Vp.ldform ( Li, Vo._D() );
253        Vp0.ldform ( Li0, Vo0._D() );
254        tmpll = Eg.lognc() - Eg0.lognc(); // likelihood is difference of norm. coefs.
255
256        cout << "i=(" << i << ") ll=" << tmpll << endl;
257
258        //
259        if ( tmpll > Egll ) { //increase of the likelihood
260            tmpindices = indices;
261            tmpindices.del ( i );
262            //search for a better match in this substructure
263            belll = egiw_bestbelow ( Eg, Eg0, tmpll, tmpindices );
264            if ( belll > maxll ) { //better match found
265                maxll = belll;
266                maxindices = tmpindices;
267            }
268        }
269    }
270    indices = maxindices;
271    return maxll;
272}
273
274ivec ARX::structure_est ( const egiw &est0 ) {
275    ivec ind = linspace ( 1, est.dimension() - 1 );
276    egiw_bestbelow ( est, est0, est.lognc() - est0.lognc(), ind );
277    return ind;
278}
279
280
281
282ivec ARX::structure_est_LT ( const egiw &est0 ) {
283    //some stuff with beliefs etc.
284    ivec belief = vec_1 ( 2 );        // default belief
285    int nbest = 1;           // nbest: how many regressors are returned
286    int nrep = 5;         // nrep: number of random repetions of structure estimation
287    double lambda   = 0.9;
288    int k = 2;
289
290    Array<str_aux> o2;
291
292    ivec ind = bdm::straux1(est._V(),est._nu(), est0._V(), est0._nu(), belief, nbest, nrep, lambda, k, o2);
293
294    return ind;
295}
296
297void ARX::from_setting ( const Setting &set ) {
298    BMEF::from_setting(set);
299
300    UI::get (rgr, set, "rgr", UI::compulsory );
301
302    dimy = yrv._dsize();
303    bdm_assert(dimy>0,"ARX::yrv should not be empty");
304    rgrlen = rgr._dsize();
305
306    int constant;
307    if ( !UI::get ( constant, set, "constant", UI::optional ) ) {
308        have_constant = true;
309    } else {
310        have_constant = constant > 0;
311    }
312    dimc = rgrlen;
313    rvc = rgr;
314
315    //init
316    shared_ptr<egiw> pri = UI::build<egiw> ( set, "prior", UI::optional );
317    if (pri) {
318        set_prior(pri.get());
319    } else {
320        shared_ptr<egiw> post = UI::build<egiw> ( set, "posterior", UI::optional );
321        set_prior(post.get());
322    }
323
324
325    shared_ptr<egiw> alt = UI::build<egiw> ( set, "alternative", UI::optional );
326    if ( alt ) {
327        bdm_assert ( alt->_dimx() == dimy, "alternative is not compatible" );
328        bdm_assert ( alt->_V().rows() == dimy + rgrlen + int(have_constant==true), "alternative is not compatible" );
329        alter_est.set_parameters ( alt->_dimx(), alt->_V(), alt->_nu() );
330        alter_est.validate();
331    }
332    // frg handled by BMEF
333
334}
335
336void ARX::set_prior(const epdf *pri) {
337    const egiw * eg=dynamic_cast<const egiw*>(pri);
338    if ( eg ) {
339        bdm_assert ( eg->_dimx() == dimy, "prior is not compatible" );
340        bdm_assert ( eg->_V().rows() == dimy + rgrlen + int(have_constant==true), "prior is not compatible" );
341        est.set_parameters ( eg->_dimx(), eg->_V(), eg->_nu() );
342        est.validate();
343    } else {
344        est.set_parameters ( dimy, zeros ( dimy + rgrlen +int(have_constant==true)) );
345        set_prior_default ( est );
346    }
347    //check alternative
348    if (alter_est.dimension()!=dimension()) {
349        alter_est = est;
350    }
351}
352
353void ARXpartialforg::bayes ( const vec &val, const vec &cond ) {
354#define LOG2  0.69314718055995
355    vec frg = cond.right(cond.length() - rgrlen);
356    vec cond_rgr = cond.left(rgrlen);       // regression vector
357
358    int dimV = est._V().cols();
359    int nparams = dimV - 1;                 // number of parameters
360    int nalternatives = 1 << nparams;    // number of alternatives
361
362    // Permutation matrix
363    mat perm_matrix = ones(nalternatives, nparams);
364    int i, j, period, idx_from, idx_to, start, end;
365    for(i = 0; i < nparams; i++) {
366        idx_from = 1 << i;
367        period   = ( idx_from << 1 );
368        idx_to   = period - 1;
369        j = 0;
370        start = idx_from;
371        end = idx_to;
372        while ( start < nalternatives ) {
373            perm_matrix.set_submatrix(start, end, i, i, 0);
374            j++;
375            start = idx_from + period * j;
376            end = idx_to + period * j;
377        }
378    }
379
380    // Array of egiws for approximation
381    Array<egiw*> egiw_array(nalternatives + 1);
382    // No. of conditioning rows in LD
383    int nalternatives_cond, position;
384
385    for(int i = 0; i < nalternatives; i++) {
386        // vector defining alternatives
387        vec vec_alt = perm_matrix.get_row(i);
388
389        // full alternative or filtered
390        if( sum(vec_alt) == vec_alt.length() )  {
391            egiw_array(i) = &alter_est;
392            continue;
393        } else if( sum(vec_alt) == 0 ) {
394            egiw_array(i) = &est;
395            continue;
396        }
397
398        nalternatives_cond = (int) sum(vec_alt) + 1;
399        ivec vec_perm(0);                   // permutation vector
400
401        for(int j = 0; j < nparams; j++) {
402            position = dimV - j - 2;
403            if ( vec_alt(position) == 0 ) {
404                vec_perm.ins(j, position + 1);
405            }
406            else {
407                vec_perm.ins(0, position + 1);
408            }
409        }
410        vec_perm.ins(0, 0);
411
412        ldmat filt (est._V(), vec_perm);
413        ldmat alt (alter_est._V(), vec_perm);
414
415        mat tmpL(dimV, dimV);
416        tmpL.set_rows( 0, alt._L().get_rows(0, nalternatives_cond - 1) );
417        tmpL.set_rows( nalternatives_cond, filt._L().get_rows(nalternatives_cond, nparams) );
418
419        vec tmpD(dimV);
420        tmpD.set_subvector( 0, alt._D()(0, nalternatives_cond - 1) );
421        tmpD.set_subvector( nalternatives_cond, filt._D()(nalternatives_cond, nparams) );
422
423        ldmat tmpLD (tmpL, tmpD);
424
425        vec_perm = sort_index(vec_perm);
426        ldmat newLD (tmpLD, vec_perm);
427
428        egiw_array(i) = new egiw(1, newLD, alter_est._nu());
429    }
430
431    // Approximation
432    double sumVecCommon;                // frequently used term
433    vec vecNu(nalternatives);           // vector of nus of components
434    vec vecD(nalternatives);            // vector of LS reminders
435    vec vecCommon(nalternatives);       // vector of common parts
436    mat matVecsTheta;                           // matrix whose rows are theta vects.
437
438    for (i = 0; i < nalternatives; i++) {
439        vecNu.shift_left( egiw_array(i)->_nu() );
440        vecD.shift_left( egiw_array(i)->_V()._D()(0) );
441        matVecsTheta.append_row( egiw_array(i)->est_theta()  );
442    }
443
444    vecCommon = elem_mult ( frg, elem_div(vecNu, vecD) );
445    sumVecCommon = sum(vecCommon);
446
447    // approximation of est. regr. coefficients
448    vec aprEstTheta(nparams);
449    aprEstTheta.zeros();
450    for (i = 0; i < nalternatives; i++) {
451        aprEstTheta +=  matVecsTheta.get_row(i) * vecCommon(i);
452    }
453    aprEstTheta /= sumVecCommon;
454
455    // approximation of degr. of freedom
456    double aprNu;
457    double A = log( sumVecCommon );             // Term 'A' in equation
458    for ( int i = 0; i < nalternatives; i++ ) {
459        A += frg(i) * ( log( vecD(i) ) - psi( 0.5 * vecNu(i) ) );
460    }
461    aprNu = ( 1 + sqrt(1 + 4 * (A - LOG2)/3 ) ) / ( 2 * (A - LOG2) );
462
463    // approximation of LS reminder D(0,0)
464    double aprD = aprNu / sumVecCommon;
465
466    // Aproximation of covariance of LS est.
467    mat aprC = zeros(nparams, nparams);
468    for ( int i = 0; i < nalternatives; i++ ) {
469        aprC += egiw_array(i)->est_theta_cov().to_mat() * frg(i);
470        vec tmp = ( matVecsTheta.get_row(i) - aprEstTheta );
471        aprC += vecCommon(i) * outer_product( tmp, tmp);
472    }
473
474    // Construct GiW pdf
475    ldmat aprCinv ( inv(aprC) );
476    vec D = concat( aprD, aprCinv._D() );
477    mat L = eye(dimV);
478    L.set_submatrix(1, 0, aprCinv._L() * aprEstTheta);
479    L.set_submatrix(1, 1, aprCinv._L());
480    ldmat aprLD (L, D);
481    est = egiw(1, aprLD, aprNu);
482
483    if ( evalll ) {
484        last_lognc = est.lognc();
485    }
486
487    // update
488    ARX::bayes ( val, cond_rgr );
489}
490
491}
Note: See TracBrowser for help on using the browser.