$search
00001 // Copyright (C) 2010-2011 NICTA (www.nicta.com.au) 00002 // Copyright (C) 2010-2011 Conrad Sanderson 00003 // Copyright (C) 2010 Dimitrios Bouzas 00004 // Copyright (C) 2011 Stanislav Funiak 00005 // 00006 // This file is part of the Armadillo C++ library. 00007 // It is provided without any warranty of fitness 00008 // for any purpose. You can redistribute this file 00009 // and/or modify it under the terms of the GNU 00010 // Lesser General Public License (LGPL) as published 00011 // by the Free Software Foundation, either version 3 00012 // of the License or (at your option) any later version. 00013 // (see http://www.opensource.org/licenses for more info) 00014 00015 00018 00019 00020 00028 template<typename eT> 00029 inline 00030 bool 00031 op_princomp::direct_princomp 00032 ( 00033 Mat<eT>& coeff_out, 00034 Mat<eT>& score_out, 00035 Col<eT>& latent_out, 00036 Col<eT>& tsquared_out, 00037 const Mat<eT>& in 00038 ) 00039 { 00040 arma_extra_debug_sigprint(); 00041 00042 const uword n_rows = in.n_rows; 00043 const uword n_cols = in.n_cols; 00044 00045 if(n_rows > 1) // more than one sample 00046 { 00047 // subtract the mean - use score_out as temporary matrix 00048 score_out = in - repmat(mean(in), n_rows, 1); 00049 00050 // singular value decomposition 00051 Mat<eT> U; 00052 Col<eT> s; 00053 00054 const bool svd_ok = svd(U,s,coeff_out,score_out); 00055 00056 if(svd_ok == false) 00057 { 00058 return false; 00059 } 00060 00061 00062 //U.reset(); // TODO: do we need this ? U will get automatically deleted anyway 00063 00064 // normalize the eigenvalues 00065 s /= std::sqrt( double(n_rows - 1) ); 00066 00067 // project the samples to the principals 00068 score_out *= coeff_out; 00069 00070 if(n_rows <= n_cols) // number of samples is less than their dimensionality 00071 { 00072 score_out.cols(n_rows-1,n_cols-1).zeros(); 00073 00074 //Col<eT> s_tmp = zeros< Col<eT> >(n_cols); 00075 Col<eT> s_tmp(n_cols); 00076 s_tmp.zeros(); 00077 00078 s_tmp.rows(0,n_rows-2) = s.rows(0,n_rows-2); 00079 s = s_tmp; 00080 00081 // compute the Hotelling's T-squared 00082 s_tmp.rows(0,n_rows-2) = eT(1) / s_tmp.rows(0,n_rows-2); 00083 00084 const Mat<eT> S = score_out * diagmat(Col<eT>(s_tmp)); 00085 tsquared_out = sum(S%S,1); 00086 } 00087 else 00088 { 00089 // compute the Hotelling's T-squared 00090 const Mat<eT> S = score_out * diagmat(Col<eT>( eT(1) / s)); 00091 tsquared_out = sum(S%S,1); 00092 } 00093 00094 // compute the eigenvalues of the principal vectors 00095 latent_out = s%s; 00096 } 00097 else // 0 or 1 samples 00098 { 00099 coeff_out.eye(n_cols, n_cols); 00100 00101 score_out.copy_size(in); 00102 score_out.zeros(); 00103 00104 latent_out.set_size(n_cols); 00105 latent_out.zeros(); 00106 00107 tsquared_out.set_size(n_rows); 00108 tsquared_out.zeros(); 00109 } 00110 00111 return true; 00112 } 00113 00114 00115 00122 template<typename eT> 00123 inline 00124 bool 00125 op_princomp::direct_princomp 00126 ( 00127 Mat<eT>& coeff_out, 00128 Mat<eT>& score_out, 00129 Col<eT>& latent_out, 00130 const Mat<eT>& in 00131 ) 00132 { 00133 arma_extra_debug_sigprint(); 00134 00135 const uword n_rows = in.n_rows; 00136 const uword n_cols = in.n_cols; 00137 00138 if(n_rows > 1) // more than one sample 00139 { 00140 // subtract the mean - use score_out as temporary matrix 00141 score_out = in - repmat(mean(in), n_rows, 1); 00142 00143 // singular value decomposition 00144 Mat<eT> U; 00145 Col<eT> s; 00146 00147 const bool svd_ok = svd(U,s,coeff_out,score_out); 00148 00149 if(svd_ok == false) 00150 { 00151 return false; 00152 } 00153 00154 00155 // U.reset(); 00156 00157 // normalize the eigenvalues 00158 s /= std::sqrt( double(n_rows - 1) ); 00159 00160 // project the samples to the principals 00161 score_out *= coeff_out; 00162 00163 if(n_rows <= n_cols) // number of samples is less than their dimensionality 00164 { 00165 score_out.cols(n_rows-1,n_cols-1).zeros(); 00166 00167 Col<eT> s_tmp = zeros< Col<eT> >(n_cols); 00168 s_tmp.rows(0,n_rows-2) = s.rows(0,n_rows-2); 00169 s = s_tmp; 00170 } 00171 00172 // compute the eigenvalues of the principal vectors 00173 latent_out = s%s; 00174 00175 } 00176 else // 0 or 1 samples 00177 { 00178 coeff_out.eye(n_cols, n_cols); 00179 00180 score_out.copy_size(in); 00181 score_out.zeros(); 00182 00183 latent_out.set_size(n_cols); 00184 latent_out.zeros(); 00185 } 00186 00187 return true; 00188 } 00189 00190 00191 00197 template<typename eT> 00198 inline 00199 bool 00200 op_princomp::direct_princomp 00201 ( 00202 Mat<eT>& coeff_out, 00203 Mat<eT>& score_out, 00204 const Mat<eT>& in 00205 ) 00206 { 00207 arma_extra_debug_sigprint(); 00208 00209 const uword n_rows = in.n_rows; 00210 const uword n_cols = in.n_cols; 00211 00212 if(n_rows > 1) // more than one sample 00213 { 00214 // subtract the mean - use score_out as temporary matrix 00215 score_out = in - repmat(mean(in), n_rows, 1); 00216 00217 // singular value decomposition 00218 Mat<eT> U; 00219 Col<eT> s; 00220 00221 const bool svd_ok = svd(U,s,coeff_out,score_out); 00222 00223 if(svd_ok == false) 00224 { 00225 return false; 00226 } 00227 00228 // U.reset(); 00229 00230 // normalize the eigenvalues 00231 s /= std::sqrt( double(n_rows - 1) ); 00232 00233 // project the samples to the principals 00234 score_out *= coeff_out; 00235 00236 if(n_rows <= n_cols) // number of samples is less than their dimensionality 00237 { 00238 score_out.cols(n_rows-1,n_cols-1).zeros(); 00239 00240 Col<eT> s_tmp = zeros< Col<eT> >(n_cols); 00241 s_tmp.rows(0,n_rows-2) = s.rows(0,n_rows-2); 00242 s = s_tmp; 00243 } 00244 } 00245 else // 0 or 1 samples 00246 { 00247 coeff_out.eye(n_cols, n_cols); 00248 score_out.copy_size(in); 00249 score_out.zeros(); 00250 } 00251 00252 return true; 00253 } 00254 00255 00256 00261 template<typename eT> 00262 inline 00263 bool 00264 op_princomp::direct_princomp 00265 ( 00266 Mat<eT>& coeff_out, 00267 const Mat<eT>& in 00268 ) 00269 { 00270 arma_extra_debug_sigprint(); 00271 00272 if(in.n_elem != 0) 00273 { 00274 // singular value decomposition 00275 Mat<eT> U; 00276 Col<eT> s; 00277 00278 const Mat<eT> tmp = in - repmat(mean(in), in.n_rows, 1); 00279 00280 const bool svd_ok = svd(U,s,coeff_out, tmp); 00281 00282 if(svd_ok == false) 00283 { 00284 return false; 00285 } 00286 } 00287 else 00288 { 00289 coeff_out.eye(in.n_cols, in.n_cols); 00290 } 00291 00292 return true; 00293 } 00294 00295 00296 00304 template<typename T> 00305 inline 00306 bool 00307 op_princomp::direct_princomp 00308 ( 00309 Mat< std::complex<T> >& coeff_out, 00310 Mat< std::complex<T> >& score_out, 00311 Col<T>& latent_out, 00312 Col< std::complex<T> >& tsquared_out, 00313 const Mat< std::complex<T> >& in 00314 ) 00315 { 00316 arma_extra_debug_sigprint(); 00317 00318 typedef std::complex<T> eT; 00319 00320 const uword n_rows = in.n_rows; 00321 const uword n_cols = in.n_cols; 00322 00323 if(n_rows > 1) // more than one sample 00324 { 00325 // subtract the mean - use score_out as temporary matrix 00326 score_out = in - repmat(mean(in), n_rows, 1); 00327 00328 // singular value decomposition 00329 Mat<eT> U; 00330 Col<T> s; 00331 00332 const bool svd_ok = svd(U,s,coeff_out,score_out); 00333 00334 if(svd_ok == false) 00335 { 00336 return false; 00337 } 00338 00339 00340 //U.reset(); 00341 00342 // normalize the eigenvalues 00343 s /= std::sqrt( double(n_rows - 1) ); 00344 00345 // project the samples to the principals 00346 score_out *= coeff_out; 00347 00348 if(n_rows <= n_cols) // number of samples is less than their dimensionality 00349 { 00350 score_out.cols(n_rows-1,n_cols-1).zeros(); 00351 00352 Col<T> s_tmp = zeros< Col<T> >(n_cols); 00353 s_tmp.rows(0,n_rows-2) = s.rows(0,n_rows-2); 00354 s = s_tmp; 00355 00356 // compute the Hotelling's T-squared 00357 s_tmp.rows(0,n_rows-2) = 1.0 / s_tmp.rows(0,n_rows-2); 00358 const Mat<eT> S = score_out * diagmat(Col<T>(s_tmp)); 00359 tsquared_out = sum(S%S,1); 00360 } 00361 else 00362 { 00363 // compute the Hotelling's T-squared 00364 const Mat<eT> S = score_out * diagmat(Col<T>(T(1) / s)); 00365 tsquared_out = sum(S%S,1); 00366 } 00367 00368 // compute the eigenvalues of the principal vectors 00369 latent_out = s%s; 00370 00371 } 00372 else // 0 or 1 samples 00373 { 00374 coeff_out.eye(n_cols, n_cols); 00375 00376 score_out.copy_size(in); 00377 score_out.zeros(); 00378 00379 latent_out.set_size(n_cols); 00380 latent_out.zeros(); 00381 00382 tsquared_out.set_size(n_rows); 00383 tsquared_out.zeros(); 00384 } 00385 00386 return true; 00387 } 00388 00389 00390 00397 template<typename T> 00398 inline 00399 bool 00400 op_princomp::direct_princomp 00401 ( 00402 Mat< std::complex<T> >& coeff_out, 00403 Mat< std::complex<T> >& score_out, 00404 Col<T>& latent_out, 00405 const Mat< std::complex<T> >& in 00406 ) 00407 { 00408 arma_extra_debug_sigprint(); 00409 00410 typedef std::complex<T> eT; 00411 00412 const uword n_rows = in.n_rows; 00413 const uword n_cols = in.n_cols; 00414 00415 if(n_rows > 1) // more than one sample 00416 { 00417 // subtract the mean - use score_out as temporary matrix 00418 score_out = in - repmat(mean(in), n_rows, 1); 00419 00420 // singular value decomposition 00421 Mat<eT> U; 00422 Col< T> s; 00423 00424 const bool svd_ok = svd(U,s,coeff_out,score_out); 00425 00426 if(svd_ok == false) 00427 { 00428 return false; 00429 } 00430 00431 00432 // U.reset(); 00433 00434 // normalize the eigenvalues 00435 s /= std::sqrt( double(n_rows - 1) ); 00436 00437 // project the samples to the principals 00438 score_out *= coeff_out; 00439 00440 if(n_rows <= n_cols) // number of samples is less than their dimensionality 00441 { 00442 score_out.cols(n_rows-1,n_cols-1).zeros(); 00443 00444 Col<T> s_tmp = zeros< Col<T> >(n_cols); 00445 s_tmp.rows(0,n_rows-2) = s.rows(0,n_rows-2); 00446 s = s_tmp; 00447 } 00448 00449 // compute the eigenvalues of the principal vectors 00450 latent_out = s%s; 00451 00452 } 00453 else // 0 or 1 samples 00454 { 00455 coeff_out.eye(n_cols, n_cols); 00456 00457 score_out.copy_size(in); 00458 score_out.zeros(); 00459 00460 latent_out.set_size(n_cols); 00461 latent_out.zeros(); 00462 } 00463 00464 return true; 00465 } 00466 00467 00468 00474 template<typename T> 00475 inline 00476 bool 00477 op_princomp::direct_princomp 00478 ( 00479 Mat< std::complex<T> >& coeff_out, 00480 Mat< std::complex<T> >& score_out, 00481 const Mat< std::complex<T> >& in 00482 ) 00483 { 00484 arma_extra_debug_sigprint(); 00485 00486 typedef std::complex<T> eT; 00487 00488 const uword n_rows = in.n_rows; 00489 const uword n_cols = in.n_cols; 00490 00491 if(n_rows > 1) // more than one sample 00492 { 00493 // subtract the mean - use score_out as temporary matrix 00494 score_out = in - repmat(mean(in), n_rows, 1); 00495 00496 // singular value decomposition 00497 Mat<eT> U; 00498 Col< T> s; 00499 00500 const bool svd_ok = svd(U,s,coeff_out,score_out); 00501 00502 if(svd_ok == false) 00503 { 00504 return false; 00505 } 00506 00507 // U.reset(); 00508 00509 // normalize the eigenvalues 00510 s /= std::sqrt( double(n_rows - 1) ); 00511 00512 // project the samples to the principals 00513 score_out *= coeff_out; 00514 00515 if(n_rows <= n_cols) // number of samples is less than their dimensionality 00516 { 00517 score_out.cols(n_rows-1,n_cols-1).zeros(); 00518 } 00519 00520 } 00521 else // 0 or 1 samples 00522 { 00523 coeff_out.eye(n_cols, n_cols); 00524 00525 score_out.copy_size(in); 00526 score_out.zeros(); 00527 } 00528 00529 return true; 00530 } 00531 00532 00533 00538 template<typename T> 00539 inline 00540 bool 00541 op_princomp::direct_princomp 00542 ( 00543 Mat< std::complex<T> >& coeff_out, 00544 const Mat< std::complex<T> >& in 00545 ) 00546 { 00547 arma_extra_debug_sigprint(); 00548 00549 typedef typename std::complex<T> eT; 00550 00551 if(in.n_elem != 0) 00552 { 00553 // singular value decomposition 00554 Mat<eT> U; 00555 Col< T> s; 00556 00557 const Mat<eT> tmp = in - repmat(mean(in), in.n_rows, 1); 00558 00559 const bool svd_ok = svd(U,s,coeff_out, tmp); 00560 00561 if(svd_ok == false) 00562 { 00563 return false; 00564 } 00565 } 00566 else 00567 { 00568 coeff_out.eye(in.n_cols, in.n_cols); 00569 } 00570 00571 return true; 00572 } 00573 00574 00575 00576 template<typename T1> 00577 inline 00578 void 00579 op_princomp::apply 00580 ( 00581 Mat<typename T1::elem_type>& out, 00582 const Op<T1,op_princomp>& in 00583 ) 00584 { 00585 arma_extra_debug_sigprint(); 00586 00587 typedef typename T1::elem_type eT; 00588 00589 const unwrap_check<T1> tmp(in.m, out); 00590 const Mat<eT>& A = tmp.M; 00591 00592 const bool status = op_princomp::direct_princomp(out, A); 00593 00594 if(status == false) 00595 { 00596 out.reset(); 00597 00598 arma_bad("princomp(): failed to converge"); 00599 } 00600 } 00601 00602 00603