comparison armadillo-2.4.4/include/armadillo_bits/op_princomp_meat.hpp @ 0:8b6102e2a9b0

Armadillo Library
author maxzanoni76 <max.zanoni@eecs.qmul.ac.uk>
date Wed, 11 Apr 2012 09:27:06 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:8b6102e2a9b0
1 // Copyright (C) 2010-2011 NICTA (www.nicta.com.au)
2 // Copyright (C) 2010-2011 Conrad Sanderson
3 // Copyright (C) 2010 Dimitrios Bouzas
4 // Copyright (C) 2011 Stanislav Funiak
5 //
6 // This file is part of the Armadillo C++ library.
7 // It is provided without any warranty of fitness
8 // for any purpose. You can redistribute this file
9 // and/or modify it under the terms of the GNU
10 // Lesser General Public License (LGPL) as published
11 // by the Free Software Foundation, either version 3
12 // of the License or (at your option) any later version.
13 // (see http://www.opensource.org/licenses for more info)
14
15
16 //! \addtogroup op_princomp
17 //! @{
18
19
20
21 //! \brief
22 //! principal component analysis -- 4 arguments version
23 //! computation is done via singular value decomposition
24 //! coeff_out -> principal component coefficients
25 //! score_out -> projected samples
26 //! latent_out -> eigenvalues of principal vectors
27 //! tsquared_out -> Hotelling's T^2 statistic
28 template<typename eT>
29 inline
30 bool
31 op_princomp::direct_princomp
32 (
33 Mat<eT>& coeff_out,
34 Mat<eT>& score_out,
35 Col<eT>& latent_out,
36 Col<eT>& tsquared_out,
37 const Mat<eT>& in
38 )
39 {
40 arma_extra_debug_sigprint();
41
42 const uword n_rows = in.n_rows;
43 const uword n_cols = in.n_cols;
44
45 if(n_rows > 1) // more than one sample
46 {
47 // subtract the mean - use score_out as temporary matrix
48 score_out = in - repmat(mean(in), n_rows, 1);
49
50 // singular value decomposition
51 Mat<eT> U;
52 Col<eT> s;
53
54 const bool svd_ok = svd(U,s,coeff_out,score_out);
55
56 if(svd_ok == false)
57 {
58 return false;
59 }
60
61
62 //U.reset(); // TODO: do we need this ? U will get automatically deleted anyway
63
64 // normalize the eigenvalues
65 s /= std::sqrt( double(n_rows - 1) );
66
67 // project the samples to the principals
68 score_out *= coeff_out;
69
70 if(n_rows <= n_cols) // number of samples is less than their dimensionality
71 {
72 score_out.cols(n_rows-1,n_cols-1).zeros();
73
74 //Col<eT> s_tmp = zeros< Col<eT> >(n_cols);
75 Col<eT> s_tmp(n_cols);
76 s_tmp.zeros();
77
78 s_tmp.rows(0,n_rows-2) = s.rows(0,n_rows-2);
79 s = s_tmp;
80
81 // compute the Hotelling's T-squared
82 s_tmp.rows(0,n_rows-2) = eT(1) / s_tmp.rows(0,n_rows-2);
83
84 const Mat<eT> S = score_out * diagmat(Col<eT>(s_tmp));
85 tsquared_out = sum(S%S,1);
86 }
87 else
88 {
89 // compute the Hotelling's T-squared
90 const Mat<eT> S = score_out * diagmat(Col<eT>( eT(1) / s));
91 tsquared_out = sum(S%S,1);
92 }
93
94 // compute the eigenvalues of the principal vectors
95 latent_out = s%s;
96 }
97 else // 0 or 1 samples
98 {
99 coeff_out.eye(n_cols, n_cols);
100
101 score_out.copy_size(in);
102 score_out.zeros();
103
104 latent_out.set_size(n_cols);
105 latent_out.zeros();
106
107 tsquared_out.set_size(n_rows);
108 tsquared_out.zeros();
109 }
110
111 return true;
112 }
113
114
115
116 //! \brief
117 //! principal component analysis -- 3 arguments version
118 //! computation is done via singular value decomposition
119 //! coeff_out -> principal component coefficients
120 //! score_out -> projected samples
121 //! latent_out -> eigenvalues of principal vectors
122 template<typename eT>
123 inline
124 bool
125 op_princomp::direct_princomp
126 (
127 Mat<eT>& coeff_out,
128 Mat<eT>& score_out,
129 Col<eT>& latent_out,
130 const Mat<eT>& in
131 )
132 {
133 arma_extra_debug_sigprint();
134
135 const uword n_rows = in.n_rows;
136 const uword n_cols = in.n_cols;
137
138 if(n_rows > 1) // more than one sample
139 {
140 // subtract the mean - use score_out as temporary matrix
141 score_out = in - repmat(mean(in), n_rows, 1);
142
143 // singular value decomposition
144 Mat<eT> U;
145 Col<eT> s;
146
147 const bool svd_ok = svd(U,s,coeff_out,score_out);
148
149 if(svd_ok == false)
150 {
151 return false;
152 }
153
154
155 // U.reset();
156
157 // normalize the eigenvalues
158 s /= std::sqrt( double(n_rows - 1) );
159
160 // project the samples to the principals
161 score_out *= coeff_out;
162
163 if(n_rows <= n_cols) // number of samples is less than their dimensionality
164 {
165 score_out.cols(n_rows-1,n_cols-1).zeros();
166
167 Col<eT> s_tmp = zeros< Col<eT> >(n_cols);
168 s_tmp.rows(0,n_rows-2) = s.rows(0,n_rows-2);
169 s = s_tmp;
170 }
171
172 // compute the eigenvalues of the principal vectors
173 latent_out = s%s;
174
175 }
176 else // 0 or 1 samples
177 {
178 coeff_out.eye(n_cols, n_cols);
179
180 score_out.copy_size(in);
181 score_out.zeros();
182
183 latent_out.set_size(n_cols);
184 latent_out.zeros();
185 }
186
187 return true;
188 }
189
190
191
192 //! \brief
193 //! principal component analysis -- 2 arguments version
194 //! computation is done via singular value decomposition
195 //! coeff_out -> principal component coefficients
196 //! score_out -> projected samples
197 template<typename eT>
198 inline
199 bool
200 op_princomp::direct_princomp
201 (
202 Mat<eT>& coeff_out,
203 Mat<eT>& score_out,
204 const Mat<eT>& in
205 )
206 {
207 arma_extra_debug_sigprint();
208
209 const uword n_rows = in.n_rows;
210 const uword n_cols = in.n_cols;
211
212 if(n_rows > 1) // more than one sample
213 {
214 // subtract the mean - use score_out as temporary matrix
215 score_out = in - repmat(mean(in), n_rows, 1);
216
217 // singular value decomposition
218 Mat<eT> U;
219 Col<eT> s;
220
221 const bool svd_ok = svd(U,s,coeff_out,score_out);
222
223 if(svd_ok == false)
224 {
225 return false;
226 }
227
228 // U.reset();
229
230 // normalize the eigenvalues
231 s /= std::sqrt( double(n_rows - 1) );
232
233 // project the samples to the principals
234 score_out *= coeff_out;
235
236 if(n_rows <= n_cols) // number of samples is less than their dimensionality
237 {
238 score_out.cols(n_rows-1,n_cols-1).zeros();
239
240 Col<eT> s_tmp = zeros< Col<eT> >(n_cols);
241 s_tmp.rows(0,n_rows-2) = s.rows(0,n_rows-2);
242 s = s_tmp;
243 }
244 }
245 else // 0 or 1 samples
246 {
247 coeff_out.eye(n_cols, n_cols);
248 score_out.copy_size(in);
249 score_out.zeros();
250 }
251
252 return true;
253 }
254
255
256
257 //! \brief
258 //! principal component analysis -- 1 argument version
259 //! computation is done via singular value decomposition
260 //! coeff_out -> principal component coefficients
261 template<typename eT>
262 inline
263 bool
264 op_princomp::direct_princomp
265 (
266 Mat<eT>& coeff_out,
267 const Mat<eT>& in
268 )
269 {
270 arma_extra_debug_sigprint();
271
272 if(in.n_elem != 0)
273 {
274 // singular value decomposition
275 Mat<eT> U;
276 Col<eT> s;
277
278 const Mat<eT> tmp = in - repmat(mean(in), in.n_rows, 1);
279
280 const bool svd_ok = svd(U,s,coeff_out, tmp);
281
282 if(svd_ok == false)
283 {
284 return false;
285 }
286 }
287 else
288 {
289 coeff_out.eye(in.n_cols, in.n_cols);
290 }
291
292 return true;
293 }
294
295
296
297 //! \brief
298 //! principal component analysis -- 4 arguments complex version
299 //! computation is done via singular value decomposition
300 //! coeff_out -> principal component coefficients
301 //! score_out -> projected samples
302 //! latent_out -> eigenvalues of principal vectors
303 //! tsquared_out -> Hotelling's T^2 statistic
304 template<typename T>
305 inline
306 bool
307 op_princomp::direct_princomp
308 (
309 Mat< std::complex<T> >& coeff_out,
310 Mat< std::complex<T> >& score_out,
311 Col<T>& latent_out,
312 Col< std::complex<T> >& tsquared_out,
313 const Mat< std::complex<T> >& in
314 )
315 {
316 arma_extra_debug_sigprint();
317
318 typedef std::complex<T> eT;
319
320 const uword n_rows = in.n_rows;
321 const uword n_cols = in.n_cols;
322
323 if(n_rows > 1) // more than one sample
324 {
325 // subtract the mean - use score_out as temporary matrix
326 score_out = in - repmat(mean(in), n_rows, 1);
327
328 // singular value decomposition
329 Mat<eT> U;
330 Col<T> s;
331
332 const bool svd_ok = svd(U,s,coeff_out,score_out);
333
334 if(svd_ok == false)
335 {
336 return false;
337 }
338
339
340 //U.reset();
341
342 // normalize the eigenvalues
343 s /= std::sqrt( double(n_rows - 1) );
344
345 // project the samples to the principals
346 score_out *= coeff_out;
347
348 if(n_rows <= n_cols) // number of samples is less than their dimensionality
349 {
350 score_out.cols(n_rows-1,n_cols-1).zeros();
351
352 Col<T> s_tmp = zeros< Col<T> >(n_cols);
353 s_tmp.rows(0,n_rows-2) = s.rows(0,n_rows-2);
354 s = s_tmp;
355
356 // compute the Hotelling's T-squared
357 s_tmp.rows(0,n_rows-2) = 1.0 / s_tmp.rows(0,n_rows-2);
358 const Mat<eT> S = score_out * diagmat(Col<T>(s_tmp));
359 tsquared_out = sum(S%S,1);
360 }
361 else
362 {
363 // compute the Hotelling's T-squared
364 const Mat<eT> S = score_out * diagmat(Col<T>(T(1) / s));
365 tsquared_out = sum(S%S,1);
366 }
367
368 // compute the eigenvalues of the principal vectors
369 latent_out = s%s;
370
371 }
372 else // 0 or 1 samples
373 {
374 coeff_out.eye(n_cols, n_cols);
375
376 score_out.copy_size(in);
377 score_out.zeros();
378
379 latent_out.set_size(n_cols);
380 latent_out.zeros();
381
382 tsquared_out.set_size(n_rows);
383 tsquared_out.zeros();
384 }
385
386 return true;
387 }
388
389
390
391 //! \brief
392 //! principal component analysis -- 3 arguments complex version
393 //! computation is done via singular value decomposition
394 //! coeff_out -> principal component coefficients
395 //! score_out -> projected samples
396 //! latent_out -> eigenvalues of principal vectors
397 template<typename T>
398 inline
399 bool
400 op_princomp::direct_princomp
401 (
402 Mat< std::complex<T> >& coeff_out,
403 Mat< std::complex<T> >& score_out,
404 Col<T>& latent_out,
405 const Mat< std::complex<T> >& in
406 )
407 {
408 arma_extra_debug_sigprint();
409
410 typedef std::complex<T> eT;
411
412 const uword n_rows = in.n_rows;
413 const uword n_cols = in.n_cols;
414
415 if(n_rows > 1) // more than one sample
416 {
417 // subtract the mean - use score_out as temporary matrix
418 score_out = in - repmat(mean(in), n_rows, 1);
419
420 // singular value decomposition
421 Mat<eT> U;
422 Col< T> s;
423
424 const bool svd_ok = svd(U,s,coeff_out,score_out);
425
426 if(svd_ok == false)
427 {
428 return false;
429 }
430
431
432 // U.reset();
433
434 // normalize the eigenvalues
435 s /= std::sqrt( double(n_rows - 1) );
436
437 // project the samples to the principals
438 score_out *= coeff_out;
439
440 if(n_rows <= n_cols) // number of samples is less than their dimensionality
441 {
442 score_out.cols(n_rows-1,n_cols-1).zeros();
443
444 Col<T> s_tmp = zeros< Col<T> >(n_cols);
445 s_tmp.rows(0,n_rows-2) = s.rows(0,n_rows-2);
446 s = s_tmp;
447 }
448
449 // compute the eigenvalues of the principal vectors
450 latent_out = s%s;
451
452 }
453 else // 0 or 1 samples
454 {
455 coeff_out.eye(n_cols, n_cols);
456
457 score_out.copy_size(in);
458 score_out.zeros();
459
460 latent_out.set_size(n_cols);
461 latent_out.zeros();
462 }
463
464 return true;
465 }
466
467
468
469 //! \brief
470 //! principal component analysis -- 2 arguments complex version
471 //! computation is done via singular value decomposition
472 //! coeff_out -> principal component coefficients
473 //! score_out -> projected samples
474 template<typename T>
475 inline
476 bool
477 op_princomp::direct_princomp
478 (
479 Mat< std::complex<T> >& coeff_out,
480 Mat< std::complex<T> >& score_out,
481 const Mat< std::complex<T> >& in
482 )
483 {
484 arma_extra_debug_sigprint();
485
486 typedef std::complex<T> eT;
487
488 const uword n_rows = in.n_rows;
489 const uword n_cols = in.n_cols;
490
491 if(n_rows > 1) // more than one sample
492 {
493 // subtract the mean - use score_out as temporary matrix
494 score_out = in - repmat(mean(in), n_rows, 1);
495
496 // singular value decomposition
497 Mat<eT> U;
498 Col< T> s;
499
500 const bool svd_ok = svd(U,s,coeff_out,score_out);
501
502 if(svd_ok == false)
503 {
504 return false;
505 }
506
507 // U.reset();
508
509 // normalize the eigenvalues
510 s /= std::sqrt( double(n_rows - 1) );
511
512 // project the samples to the principals
513 score_out *= coeff_out;
514
515 if(n_rows <= n_cols) // number of samples is less than their dimensionality
516 {
517 score_out.cols(n_rows-1,n_cols-1).zeros();
518 }
519
520 }
521 else // 0 or 1 samples
522 {
523 coeff_out.eye(n_cols, n_cols);
524
525 score_out.copy_size(in);
526 score_out.zeros();
527 }
528
529 return true;
530 }
531
532
533
534 //! \brief
535 //! principal component analysis -- 1 argument complex version
536 //! computation is done via singular value decomposition
537 //! coeff_out -> principal component coefficients
538 template<typename T>
539 inline
540 bool
541 op_princomp::direct_princomp
542 (
543 Mat< std::complex<T> >& coeff_out,
544 const Mat< std::complex<T> >& in
545 )
546 {
547 arma_extra_debug_sigprint();
548
549 typedef typename std::complex<T> eT;
550
551 if(in.n_elem != 0)
552 {
553 // singular value decomposition
554 Mat<eT> U;
555 Col< T> s;
556
557 const Mat<eT> tmp = in - repmat(mean(in), in.n_rows, 1);
558
559 const bool svd_ok = svd(U,s,coeff_out, tmp);
560
561 if(svd_ok == false)
562 {
563 return false;
564 }
565 }
566 else
567 {
568 coeff_out.eye(in.n_cols, in.n_cols);
569 }
570
571 return true;
572 }
573
574
575
576 template<typename T1>
577 inline
578 void
579 op_princomp::apply
580 (
581 Mat<typename T1::elem_type>& out,
582 const Op<T1,op_princomp>& in
583 )
584 {
585 arma_extra_debug_sigprint();
586
587 typedef typename T1::elem_type eT;
588
589 const unwrap_check<T1> tmp(in.m, out);
590 const Mat<eT>& A = tmp.M;
591
592 const bool status = op_princomp::direct_princomp(out, A);
593
594 if(status == false)
595 {
596 out.reset();
597
598 arma_bad("princomp(): failed to converge");
599 }
600 }
601
602
603
604 //! @}