Changeset 333

Show
Ignore:
Timestamp:
04/30/09 13:57:39 (15 years ago)
Author:
dedecius
Message:

Implementation of GiW mixtures and their approximation by a single mixture

Location:
bdm/stat
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • bdm/stat/emix.cpp

    r271 r333  
    4949        it_assert_debug(isnamed(), "rvs are not assigned"); 
    5050        return new mratio(this,rv); 
     51}; 
     52 
     53void egiwmix::set_parameters ( const vec &w0, const Array<egiw*> &Coms0, bool copy ) { 
     54        w = w0/sum ( w0 ); 
     55        dim = Coms0(0)->dimension(); 
     56        int i; 
     57        for ( i=0;i<w.length();i++ ) { 
     58                it_assert_debug ( dim== ( Coms0 ( i )->dimension() ),"Component sizes do not match!" ); 
     59        } 
     60        if ( copy ) { 
     61                Coms.set_length(Coms0.length()); 
     62                for ( i=0;i<w.length();i++ ) {it_error("Not imp..."); 
     63                        *Coms ( i ) =*Coms0 ( i );} 
     64                destroyComs=true; 
     65        } 
     66        else { 
     67                Coms = Coms0; 
     68                destroyComs=false; 
     69        } 
     70} 
     71 
     72vec egiwmix::sample() const { 
     73        //Sample which component 
     74        vec cumDist = cumsum ( w ); 
     75        double u0; 
     76        #pragma omp critical 
     77        u0 = UniRNG.sample(); 
     78 
     79        int i=0; 
     80        while ( ( cumDist ( i ) <u0 ) && ( i< ( w.length()-1 ) ) ) {i++;} 
     81 
     82        return Coms ( i )->sample(); 
     83} 
     84 
     85vec egiwmix::mean() const { 
     86        int i; vec mu = zeros ( dim ); 
     87        for ( i = 0;i < w.length();i++ ) {mu += w ( i ) * Coms ( i )->mean(); } 
     88        return mu; 
     89} 
     90 
     91vec egiwmix::variance() const { 
     92        // non-central moment 
     93        vec mom2 = zeros ( dim ); 
     94        for ( int i = 0;i < w.length();i++ ) { 
     95                // pow is overloaded, we have to use another approach 
     96                mom2 += w ( i ) * (Coms(i)->variance() + elem_mult ( Coms(i)->mean(), Coms(i)->mean() ));  
     97        } 
     98        // central moment 
     99        // pow is overloaded, we have to use another approach 
     100        return mom2 - elem_mult( mean(), mean() ); 
     101} 
     102 
     103emix* egiwmix::marginal(const RV &rv) const{ 
     104        it_assert_debug(isnamed(), "rvs are not assigned"); 
     105                         
     106        Array<epdf*> Cn(Coms.length()); 
     107        for(int i=0;i<Coms.length();i++){Cn(i)=Coms(i)->marginal(rv);} 
     108        emix* tmp = new emix(); 
     109        tmp->set_parameters(w,Cn,false); 
     110        tmp->ownComs(); 
     111        return tmp; 
     112} 
     113 
     114egiw*   egiwmix::approx() { 
     115        // NB: dimx == 1 !!! 
     116        // The following code might look a bit spaghetti-like, 
     117        // consult Dedecius, K. et al.: Partial forgetting in AR models. 
     118 
     119        double sumVecCommon;                            // common part for many terms in eq. 
     120        int len = w.length();                           // no. of mix components         
     121        int dimLS = Coms(1)->_V()._D().length() - 1;    // dim of LS 
     122        vec vecNu(len);                                 // vector of dfms of components 
     123        vec vecD(len);                                  // vector of LS reminders of comps. 
     124        vec vecCommon(len);                             // vector of common parts 
     125        mat matVecsTheta;                               // matrix which rows are theta vects. 
     126 
     127        // fill in the vectors vecNu, vecD and matVecsTheta 
     128        for ( int i=0; i<len; i++ ) { 
     129                vecNu.shift_left( Coms(i)->_nu() ); 
     130                vecD.shift_left( Coms(i)->_V()._D()(0) ); 
     131                matVecsTheta.append_row( Coms(i)->est_theta()  ); 
     132        } 
     133 
     134        // calculate the common parts and their sum 
     135        vecCommon = elem_mult ( w, elem_div(vecNu, vecD) ); 
     136        sumVecCommon = sum(vecCommon); 
     137 
     138        // LS estimator of theta 
     139        vec aprEstTheta(dimLS);  aprEstTheta.zeros(); 
     140        for ( int i=0; i<len; i++ ) { 
     141                aprEstTheta +=  matVecsTheta.get_row( i ) * vecCommon ( i ); 
     142        } 
     143        aprEstTheta /= sumVecCommon; 
     144         
     145         
     146        // LS estimator of dfm 
     147        double aprNu; 
     148        double A = log( sumVecCommon );         // Term 'A' in equation 
     149 
     150        for ( int i=0; i<len; i++ ) { 
     151                A += w(i) * ( log( vecD(i) ) - psi( 0.5 * vecNu(i) ) ); 
     152        } 
     153 
     154        aprNu = ( 1 + sqrt(1 + 2 * (A - LOG2)/3 ) ) / ( 2 * (A - LOG2) ); 
     155 
     156 
     157        // LS reminder (term D(0,0) in C-syntax) 
     158        double aprD = aprNu / sumVecCommon; 
     159 
     160        // Aproximation of cov 
     161        // the following code is very numerically sensitive, thus 
     162        // we have to eliminate decompositions etc. as much as possible 
     163        mat aprC = zeros(dimLS, dimLS); 
     164        for ( int i=0; i<len; i++ ) { 
     165                aprC += Coms(i)->est_theta_cov().to_mat() * w(i);  
     166                vec tmp = ( matVecsTheta.get_row(i) - aprEstTheta ); 
     167                aprC += vecCommon(i) * outer_product( tmp, tmp); 
     168        } 
     169 
     170        // Construct GiW pdf :: BEGIN 
     171        ldmat aprCinv ( inv(aprC) ); 
     172        vec D = concat( aprD, aprCinv._D() ); 
     173        mat L = eye(len+1); 
     174        L.set_submatrix(1,0, aprCinv._L() * aprEstTheta); 
     175        L.set_submatrix(1,1, aprCinv._L()); 
     176        ldmat aprLD (L, D); 
     177 
     178        egiw* aprgiw = new egiw(1, aprLD, aprNu); 
     179        return aprgiw; 
    51180}; 
    52181 
  • bdm/stat/emix.h

    r310 r333  
    1313#ifndef MX_H 
    1414#define MX_H 
     15 
     16#define LOG2  0.69314718055995   
    1517 
    1618#include "libBM.h" 
     
    159161}; 
    160162 
     163 
     164/*! 
     165* \brief Mixture of egiws 
     166 
     167*/ 
     168class egiwmix : public egiw { 
     169protected: 
     170        //! weights of the components 
     171        vec w; 
     172        //! Component (epdfs) 
     173        Array<egiw*> Coms; 
     174        //!Flag if owning Coms 
     175        bool destroyComs; 
     176public: 
     177        //!Default constructor 
     178        egiwmix ( ) : egiw ( ) {}; 
     179 
     180        //! Set weights \c w and components \c Coms 
     181        //!By default Coms are copied inside. Parameter \c copy can be set to false if Coms live externally. Use method ownComs() if Coms should be destroyed by the destructor. 
     182        void set_parameters ( const vec &w, const Array<egiw*> &Coms, bool copy=false ); 
     183 
     184        //!return expected value 
     185        vec mean() const; 
     186 
     187        //!return a sample from the density 
     188        vec sample() const; 
     189 
     190        //!return the expected variance 
     191        vec variance() const; 
     192 
     193        // TODO!!! Defined to follow ANSI and/or for future development 
     194        void mean_mat ( mat &M, mat&R ) const {}; 
     195        double evallog_nn ( const vec &val ) const {return 0;}; 
     196        double lognc () const {return 0;}; 
     197        emix* marginal ( const RV &rv ) const; 
     198 
     199//Access methods 
     200        //! returns a pointer to the internal mean value. Use with Care! 
     201        vec& _w() {return w;} 
     202        virtual ~egiwmix() {if ( destroyComs ) {for ( int i=0;i<Coms.length();i++ ) {delete Coms ( i );}}} 
     203        //! Auxiliary function for taking ownership of the Coms() 
     204        void ownComs() {destroyComs=true;} 
     205 
     206        //!access function 
     207        egiw* _Coms ( int i ) {return Coms ( i );} 
     208 
     209        void set_rv(const RV &rv){ 
     210                egiw::set_rv(rv); 
     211                for(int i=0;i<Coms.length();i++){Coms(i)->set_rv(rv);} 
     212        } 
     213 
     214        //! Approximation of a GiW mix by a single GiW pdf 
     215        egiw* approx(); 
     216}; 
     217 
    161218/*! \brief Chain rule decomposition of epdf 
    162219