Changeset 477 for library/bdm/stat/emix.cpp
- Timestamp:
- 08/05/09 14:40:03 (15 years ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
library/bdm/stat/emix.cpp
r464 r477 1 1 #include "emix.h" 2 2 3 namespace bdm {3 namespace bdm { 4 4 5 5 void emix::set_parameters ( const vec &w0, const Array<epdf*> &Coms0, bool copy ) { 6 w = w0 /sum ( w0 );7 dim = Coms0 (0)->dimension();8 bool isnamed = Coms0 (0)->isnamed();6 w = w0 / sum ( w0 ); 7 dim = Coms0 ( 0 )->dimension(); 8 bool isnamed = Coms0 ( 0 )->isnamed(); 9 9 int i; 10 10 RV tmp_rv; 11 if ( isnamed) tmp_rv=Coms0(0)->_rv();12 13 for ( i =0;i<w.length();i++ ) {14 it_assert_debug ( dim == ( Coms0 ( i )->dimension() ),"Component sizes do not match!" );15 it_assert_debug ( !isnamed || tmp_rv.equal ( Coms0 ( i )->_rv() ),"Component RVs do not match!" );11 if ( isnamed ) tmp_rv = Coms0 ( 0 )->_rv(); 12 13 for ( i = 0; i < w.length(); i++ ) { 14 it_assert_debug ( dim == ( Coms0 ( i )->dimension() ), "Component sizes do not match!" ); 15 it_assert_debug ( !isnamed || tmp_rv.equal ( Coms0 ( i )->_rv() ), "Component RVs do not match!" ); 16 16 } 17 17 if ( copy ) { 18 Coms.set_length(Coms0.length()); 19 for ( i=0;i<w.length();i++ ) {it_error("Not imp..."); 20 *Coms ( i ) =*Coms0 ( i );} 21 destroyComs=true; 22 } 23 else { 18 Coms.set_length ( Coms0.length() ); 19 for ( i = 0; i < w.length(); i++ ) { 20 it_error ( "Not imp..." ); 21 *Coms ( i ) = *Coms0 ( i ); 22 } 23 destroyComs = true; 24 } else { 24 25 Coms = Coms0; 25 destroyComs =false;26 } 27 if ( isnamed) epdf::set_rv(tmp_rv); //coms aer already OK, no need for set_rv26 destroyComs = false; 27 } 28 if ( isnamed ) epdf::set_rv ( tmp_rv ); //coms aer already OK, no need for set_rv 28 29 } 29 30 … … 32 33 vec cumDist = cumsum ( w ); 33 34 double u0; 34 35 #pragma omp critical 35 36 u0 = UniRNG.sample(); 36 37 37 int i=0; 38 while ( ( cumDist ( i ) <u0 ) && ( i< ( w.length()-1 ) ) ) {i++;} 38 int i = 0; 39 while ( ( cumDist ( i ) < u0 ) && ( i < ( w.length() - 1 ) ) ) { 40 i++; 41 } 39 42 40 43 return Coms ( i )->sample(); 41 44 } 42 45 43 emix* emix::marginal(const RV &rv) const{ 44 it_assert_debug(isnamed(), "rvs are not assigned"); 45 46 Array<epdf*> Cn(Coms.length()); 47 for(int i=0;i<Coms.length();i++){Cn(i)=Coms(i)->marginal(rv);} 46 emix* emix::marginal ( const RV &rv ) const { 47 it_assert_debug ( isnamed(), "rvs are not assigned" ); 48 49 Array<epdf*> Cn ( Coms.length() ); 50 for ( int i = 0; i < Coms.length(); i++ ) { 51 Cn ( i ) = Coms ( i )->marginal ( rv ); 52 } 48 53 emix* tmp = new emix(); 49 tmp->set_parameters (w,Cn,false);54 tmp->set_parameters ( w, Cn, false ); 50 55 tmp->ownComs(); 51 56 return tmp; 52 57 } 53 58 54 mratio* emix::condition (const RV &rv) const{55 it_assert_debug (isnamed(), "rvs are not assigned");56 return new mratio (this,rv);59 mratio* emix::condition ( const RV &rv ) const { 60 it_assert_debug ( isnamed(), "rvs are not assigned" ); 61 return new mratio ( this, rv ); 57 62 }; 58 63 59 64 void egiwmix::set_parameters ( const vec &w0, const Array<egiw*> &Coms0, bool copy ) { 60 w = w0 /sum ( w0 );61 dim = Coms0 (0)->dimension();65 w = w0 / sum ( w0 ); 66 dim = Coms0 ( 0 )->dimension(); 62 67 int i; 63 for ( i =0;i<w.length();i++ ) {64 it_assert_debug ( dim == ( Coms0 ( i )->dimension() ),"Component sizes do not match!" );68 for ( i = 0; i < w.length(); i++ ) { 69 it_assert_debug ( dim == ( Coms0 ( i )->dimension() ), "Component sizes do not match!" ); 65 70 } 66 71 if ( copy ) { 67 Coms.set_length(Coms0.length()); 68 for ( i=0;i<w.length();i++ ) {it_error("Not imp..."); 69 *Coms ( i ) =*Coms0 ( i );} 70 destroyComs=true; 71 } 72 else { 72 Coms.set_length ( Coms0.length() ); 73 for ( i = 0; i < w.length(); i++ ) { 74 it_error ( "Not imp..." ); 75 *Coms ( i ) = *Coms0 ( i ); 76 } 77 destroyComs = true; 78 } else { 73 79 Coms = Coms0; 74 destroyComs =false;80 destroyComs = false; 75 81 } 76 82 } … … 80 86 vec cumDist = cumsum ( w ); 81 87 double u0; 82 88 #pragma omp critical 83 89 u0 = UniRNG.sample(); 84 90 85 int i=0; 86 while ( ( cumDist ( i ) <u0 ) && ( i< ( w.length()-1 ) ) ) {i++;} 91 int i = 0; 92 while ( ( cumDist ( i ) < u0 ) && ( i < ( w.length() - 1 ) ) ) { 93 i++; 94 } 87 95 88 96 return Coms ( i )->sample(); … … 90 98 91 99 vec egiwmix::mean() const { 92 int i; vec mu = zeros ( dim ); 93 for ( i = 0;i < w.length();i++ ) {mu += w ( i ) * Coms ( i )->mean(); } 100 int i; 101 vec mu = zeros ( dim ); 102 for ( i = 0; i < w.length(); i++ ) { 103 mu += w ( i ) * Coms ( i )->mean(); 104 } 94 105 return mu; 95 106 } … … 98 109 // non-central moment 99 110 vec mom2 = zeros ( dim ); 100 for ( int i = 0; i < w.length();i++ ) {111 for ( int i = 0; i < w.length(); i++ ) { 101 112 // pow is overloaded, we have to use another approach 102 mom2 += w ( i ) * ( Coms(i)->variance() + elem_mult ( Coms(i)->mean(), Coms(i)->mean() ));113 mom2 += w ( i ) * ( Coms ( i )->variance() + elem_mult ( Coms ( i )->mean(), Coms ( i )->mean() ) ); 103 114 } 104 115 // central moment 105 116 // pow is overloaded, we have to use another approach 106 return mom2 - elem_mult( mean(), mean() ); 107 } 108 109 emix* egiwmix::marginal(const RV &rv) const{ 110 it_assert_debug(isnamed(), "rvs are not assigned"); 111 112 Array<epdf*> Cn(Coms.length()); 113 for(int i=0;i<Coms.length();i++){Cn(i)=Coms(i)->marginal(rv);} 117 return mom2 - elem_mult ( mean(), mean() ); 118 } 119 120 emix* egiwmix::marginal ( const RV &rv ) const { 121 it_assert_debug ( isnamed(), "rvs are not assigned" ); 122 123 Array<epdf*> Cn ( Coms.length() ); 124 for ( int i = 0; i < Coms.length(); i++ ) { 125 Cn ( i ) = Coms ( i )->marginal ( rv ); 126 } 114 127 emix* tmp = new emix(); 115 tmp->set_parameters (w,Cn,false);128 tmp->set_parameters ( w, Cn, false ); 116 129 tmp->ownComs(); 117 130 return tmp; … … 124 137 125 138 double sumVecCommon; // common part for many terms in eq. 126 int len = w.length(); // no. of mix components 127 int dimLS = Coms (1)->_V()._D().length() - 1; // dim of LS128 vec vecNu (len); // vector of dfms of components129 vec vecD (len); // vector of LS reminders of comps.130 vec vecCommon (len); // vector of common parts139 int len = w.length(); // no. of mix components 140 int dimLS = Coms ( 1 )->_V()._D().length() - 1; // dim of LS 141 vec vecNu ( len ); // vector of dfms of components 142 vec vecD ( len ); // vector of LS reminders of comps. 143 vec vecCommon ( len ); // vector of common parts 131 144 mat matVecsTheta; // matrix which rows are theta vects. 132 145 133 146 // fill in the vectors vecNu, vecD and matVecsTheta 134 for ( int i =0; i<len; i++ ) {135 vecNu.shift_left ( Coms(i)->_nu() );136 vecD.shift_left ( Coms(i)->_V()._D()(0) );137 matVecsTheta.append_row ( Coms(i)->est_theta());147 for ( int i = 0; i < len; i++ ) { 148 vecNu.shift_left ( Coms ( i )->_nu() ); 149 vecD.shift_left ( Coms ( i )->_V()._D() ( 0 ) ); 150 matVecsTheta.append_row ( Coms ( i )->est_theta() ); 138 151 } 139 152 140 153 // calculate the common parts and their sum 141 vecCommon = elem_mult ( w, elem_div (vecNu, vecD) );142 sumVecCommon = sum (vecCommon);154 vecCommon = elem_mult ( w, elem_div ( vecNu, vecD ) ); 155 sumVecCommon = sum ( vecCommon ); 143 156 144 157 // LS estimator of theta 145 vec aprEstTheta(dimLS); aprEstTheta.zeros(); 146 for ( int i=0; i<len; i++ ) { 147 aprEstTheta += matVecsTheta.get_row( i ) * vecCommon ( i ); 158 vec aprEstTheta ( dimLS ); 159 aprEstTheta.zeros(); 160 for ( int i = 0; i < len; i++ ) { 161 aprEstTheta += matVecsTheta.get_row ( i ) * vecCommon ( i ); 148 162 } 149 163 aprEstTheta /= sumVecCommon; 150 151 164 165 152 166 // LS estimator of dfm 153 167 double aprNu; 154 double A = log ( sumVecCommon ); // Term 'A' in equation155 156 for ( int i =0; i<len; i++ ) {157 A += w (i) * ( log( vecD(i) ) - psi( 0.5 * vecNu(i) ) );158 } 159 160 aprNu = ( 1 + sqrt (1 + 2 * (A - LOG2)/3 ) ) / ( 2 * (A - LOG2) );168 double A = log ( sumVecCommon ); // Term 'A' in equation 169 170 for ( int i = 0; i < len; i++ ) { 171 A += w ( i ) * ( log ( vecD ( i ) ) - psi ( 0.5 * vecNu ( i ) ) ); 172 } 173 174 aprNu = ( 1 + sqrt ( 1 + 2 * ( A - LOG2 ) / 3 ) ) / ( 2 * ( A - LOG2 ) ); 161 175 162 176 … … 167 181 // the following code is very numerically sensitive, thus 168 182 // we have to eliminate decompositions etc. as much as possible 169 mat aprC = zeros (dimLS, dimLS);170 for ( int i =0; i<len; i++ ) {171 aprC += Coms (i)->est_theta_cov().to_mat() * w(i);172 vec tmp = ( matVecsTheta.get_row (i) - aprEstTheta );173 aprC += vecCommon (i) * outer_product( tmp, tmp);183 mat aprC = zeros ( dimLS, dimLS ); 184 for ( int i = 0; i < len; i++ ) { 185 aprC += Coms ( i )->est_theta_cov().to_mat() * w ( i ); 186 vec tmp = ( matVecsTheta.get_row ( i ) - aprEstTheta ); 187 aprC += vecCommon ( i ) * outer_product ( tmp, tmp ); 174 188 } 175 189 176 190 // Construct GiW pdf :: BEGIN 177 ldmat aprCinv ( inv (aprC) );178 vec D = concat ( aprD, aprCinv._D() );179 mat L = eye (dimLS+1);180 L.set_submatrix (1,0, aprCinv._L() * aprEstTheta);181 L.set_submatrix (1,1, aprCinv._L());182 ldmat aprLD ( L, D);183 184 egiw* aprgiw = new egiw (1, aprLD, aprNu);191 ldmat aprCinv ( inv ( aprC ) ); 192 vec D = concat ( aprD, aprCinv._D() ); 193 mat L = eye ( dimLS + 1 ); 194 L.set_submatrix ( 1, 0, aprCinv._L() * aprEstTheta ); 195 L.set_submatrix ( 1, 1, aprCinv._L() ); 196 ldmat aprLD ( L, D ); 197 198 egiw* aprgiw = new egiw ( 1, aprLD, aprNu ); 185 199 return aprgiw; 186 200 };