00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "PCA.h"
00020
00021 using std::ostringstream;
00022 using namespace Marsyas;
00023
00024 #define SIGN(a, b) ( (b) < 0 ? -fabs(a) : fabs(a) )
00025
00026
00027 PCA::PCA(mrs_string name):MarSystem("PCA",name)
00028 {
00029
00030
00031
00032 addControls();
00033 }
00034
00035
00036 PCA::PCA(const PCA& a): MarSystem(a)
00037 {
00038 evals_ = NULL;
00039 interm_ = NULL;
00040 }
00041
00042
00043 PCA::~PCA()
00044 {
00045 delete [] evals_;
00046 delete [] interm_;
00047 }
00048
00049 MarSystem*
00050 PCA::clone() const
00051 {
00052 return new PCA(*this);
00053 }
00054
00055 void
00056 PCA::addControls()
00057 {
00058 npcs_.create(3,3);
00059
00060 addctrl("mrs_natural/npc",4);
00061 setctrlState("mrs_natural/npc",true);
00062 addctrl("mrs_realvec/pcs",npcs_);
00063 dims_ = 0;
00064 evals_ = NULL;
00065 interm_ = NULL;
00066 }
00067
00068 void
00069 PCA::myUpdate(MarControlPtr sender)
00070 {
00071 MRSDIAG("PCA.cpp - PCA:myUpdate");
00072
00073 setctrl("mrs_natural/onSamples", getctrl("mrs_natural/inSamples"));
00074 setctrl("mrs_natural/onObservations", getctrl("mrs_natural/npc"));
00075 setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00076
00077 inObservations_ = getctrl("mrs_natural/inObservations")->to<mrs_natural>();
00078 onObservations_ = getctrl("mrs_natural/onObservations")->to<mrs_natural>();
00079
00080 npc_ = getctrl("mrs_natural/npc")->to<mrs_natural>();
00081
00082 if( npcs_.getRows() != inObservations_-1 || npcs_.getCols() != npc_ )
00083 npcs_.create(inObservations_-1,npc_);
00084
00085 if( npc_ != onObservations_-1 ){
00086
00087 updControl("mrs_natural/onObservations", npc_ +1);
00088 onObservations_ = npc_+1;
00089 }
00090
00091 if( dims_ != inObservations_-1 )
00092 {
00093 dims_ = inObservations_-1;
00094 corr_matrix_.create(dims_,dims_);
00095 temp_matrix_.create(dims_, inSamples_);
00096 evals_ = new mrs_real[dims_];
00097 interm_ = new mrs_real[dims_];
00098 }
00099
00100 ostringstream oss;
00101 for (int i=1 ; i <= npc_ ; ++i )
00102 {
00103 oss << "PC_" << i << ",";
00104 }
00105 setctrl("mrs_string/onObsNames", oss.str());
00106 }
00107
00108 void
00109 PCA::myProcess(realvec& in, realvec& out)
00110 {
00111 mrs_natural t,o;
00112 mrs_natural o1,o2;
00113
00114
00115 for (o=0; o < inObservations_-1; o++)
00116 for (t = 0; t < inSamples_; t++)
00117 {
00118 temp_matrix_(o, t) = in(o,t);
00119 }
00120
00121
00122
00123
00124
00125
00126
00127 temp_matrix_.meanObs(means_);
00128 temp_matrix_.stdObs(stds_);
00129
00130
00131
00132
00133
00134
00135
00136 for (o=0; o < inObservations_-1; o++)
00137 for (t = 0; t < inSamples_; t++)
00138 temp_matrix_(o,t) = ( temp_matrix_(o,t) - means_(o) ) / ( sqrt((mrs_real)inSamples_) * stds_(o) ) ;
00139
00140
00141
00142 for ( o1 = 0 ; o1 < inObservations_-2 ; o1++ )
00143 {
00144 corr_matrix_(o1,o1) = 1.0;
00145 for ( o2 = o1+1 ; o2 < inObservations_-1 ; o2++ )
00146 {
00147 corr_matrix_(o1,o2) = 0.0;
00148 for( t=0 ; t < inSamples_ ; t++ )
00149 corr_matrix_(o1,o2) += temp_matrix_(o1,t) * temp_matrix_(o2,t);
00150 corr_matrix_(o2,o1) = corr_matrix_(o1,o2);
00151 }
00152 }
00153 corr_matrix_(inObservations_-2, inObservations_-2) = 1.0;
00154
00155
00156
00157
00158
00159 tred2(corr_matrix_, inObservations_-1, evals_, interm_);
00160
00161
00162
00163 tqli( evals_, interm_, inObservations_-1, corr_matrix_);
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 for( t=0 ; t<inSamples_ ; t++ )
00187 {
00188 for( o=0 ; o<inObservations_ -1; o++ )
00189 interm_[o] = in(o,t);
00190
00191 for( o=0 ; o<onObservations_ -1; o++ )
00192 {
00193 out(o,t) = 0.0;
00194 for(o2=0 ; o2 < inObservations_ -1; o2++)
00195 {
00196 out(o,t) += interm_[o2] * corr_matrix_(o2,inObservations_-o-2);
00197 npcs_(o2,o) = corr_matrix_(o2,inObservations_-o-2);
00198 }
00199 }
00200 }
00201
00202
00203
00204 for( t=0 ; t<inSamples_ ; t++ )
00205 out(onObservations_-1, t) = in(inObservations_-1, t);
00206 setctrl("mrs_realvec/pcs",npcs_);
00207
00208 }
00209
00210
00211 void
00212 PCA::tred2(realvec &a, mrs_natural m, mrs_real *d, mrs_real *e)
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 {
00224 mrs_natural l, k, j, i;
00225 mrs_real scale, hh, h, g, f;
00226
00227 for (i = m-1; i > 0; i--)
00228 {
00229 l = i - 1;
00230 h = scale = 0.0;
00231 if (l > 0)
00232 {
00233 for (k = 0; k <= l; k++)
00234 scale += fabs(a(i,k));
00235 if (scale == 0.0)
00236 e[i] = a(i,l);
00237 else
00238 {
00239 for (k = 0; k <= l; k++)
00240 {
00241 a(i,k) /= scale;
00242 h += a(i,k) * a(i,k);
00243 }
00244 f = a(i,l);
00245 g = f>0 ? -sqrt(h) : sqrt(h);
00246 e[i] = scale * g;
00247
00248 h -= f * g;
00249 a(i,l) = f - g;
00250 f = 0.0;
00251 for (j = 0; j <= l; j++)
00252 {
00253 a(j,i) = a(i,j)/h;
00254 g = 0.0;
00255 for (k = 0; k <= j; k++)
00256 g += a(j,k) * a(i,k);
00257 for (k = j+1; k <= l; k++)
00258 g += a(k,j) * a(i,k);
00259 e[j] = g / h;
00260 f += e[j] * a(i,j);
00261 }
00262 hh = f / (h + h);
00263 for (j = 0; j <= l; j++)
00264 {
00265 f = a(i,j);
00266 e[j] = g = e[j] - hh * f;
00267 for (k = 0; k <= j; k++)
00268 a(j,k) -= (f * e[k] + g * a(i,k));
00269 }
00270 }
00271 }
00272 else
00273 e[i] = a(i,l);
00274 d[i] = h;
00275 }
00276 d[0] = 0.0;
00277 e[0] = 0.0;
00278 for (i = 0; i < m; ++i)
00279 {
00280 l = i - 1;
00281 if (d[i])
00282 {
00283 for (j = 0; j <= l; j++)
00284 {
00285 g = 0.0;
00286 for (k = 0; k <= l; k++)
00287 g += a(i,k) * a(k,j);
00288 for (k = 0; k <= l; k++)
00289 a(k,j) -= g * a(k,i);
00290 }
00291 }
00292 d[i] = a(i,i);
00293 a(i,i) = 1.0;
00294
00295 for (j = 0; j <= l; j++)
00296 a(j,i) = a(i,j) = 0.0;
00297 }
00298 }
00299
00300
00301 void
00302 PCA::tqli(mrs_real d[], mrs_real e[], mrs_natural m, realvec &z)
00303
00304
00305
00306
00307 {
00308 mrs_natural n, l, iter, i, k;
00309 mrs_real s, r, p, g, f, dd, c, b;
00310
00311 for (i = 1; i < m; ++i)
00312 e[i-1] = e[i];
00313 e[m-1] = 0.0;
00314 for (l = 0; l < m; l++)
00315 {
00316 iter = 0;
00317 do
00318 {
00319 for (n = l; n < m-1; n++)
00320 {
00321 dd = fabs(d[n]) + fabs(d[n+1]);
00322 if (fabs(e[n]) + dd == dd) break;
00323 }
00324 if (n != l)
00325 {
00326 MRSASSERT( iter++ != 30 );
00327
00328 g = (d[l+1] - d[l]) / (2.0 * e[l]);
00329 r = sqrt((g * g) + 1.0);
00330 g = d[n] - d[l] + e[l] / (g + SIGN(r, g));
00331 s = c = 1.0;
00332 p = 0.0;
00333 for (i = n-1; i >= l; i--)
00334 {
00335 f = s * e[i];
00336 b = c * e[i];
00337 if (fabs(f) >= fabs(g))
00338 {
00339 c = g / f;
00340 r = sqrt((c * c) + 1.0);
00341 e[i+1] = f * r;
00342 c *= (s = 1.0/r);
00343 }
00344 else
00345 {
00346 s = f / g;
00347 r = sqrt((s * s) + 1.0);
00348 e[i+1] = g * r;
00349 s *= (c = 1.0/r);
00350 }
00351 g = d[i+1] - p;
00352 r = (d[i] - g) * s + 2.0 * c * b;
00353 p = s * r;
00354 d[i+1] = g + p;
00355 g = c * r - b;
00356 for (k = 0; k < m; k++)
00357 {
00358 f = z(k,i+1);
00359 z(k,i+1) = s * z(k,i) + c * f;
00360 z(k,i) = c * z(k,i) - s * f;
00361 }
00362 }
00363 d[l] = d[l] - p;
00364 e[l] = g;
00365 e[n] = 0.0;
00366 }
00367 } while (n != l);
00368 }
00369 }
00370
00371
00372
00373
00374
00375
00376
00377