libcrn  3.9.5
A document image processing library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CRNPCA.cpp
Go to the documentation of this file.
1 /* Copyright 2009-2016 Jean DUONG, INSA-Lyon, CoReNum, ENS-Lyon
2  *
3  * This file is part of libcrn.
4  *
5  * libcrn is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * libcrn is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with libcrn. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * file: CRNPCA.cpp
19  * \author Jean DUONG, Yann LEYDIER
20  */
21 
22 #include <stdio.h>
23 #include <iostream>
24 
25 #include <CRNException.h>
26 #include <CRNStatistics/CRNPCA.h>
27 #include <CRNData/CRNDataFactory.h>
28 #include <CRNi18n.h>
29 
30 #include <CRNMath/CRNMath.h>
32 
33 using namespace crn;
34 
41 PCA::PCA(const MatrixDouble &data, bool data_reduction_flag)
42 {
43  dimension = data.GetCols();
44 
45  size_t nb_patterns = data.GetRows();
46  bool status = ((nb_patterns > 1) && (dimension > 1));
47 
48  if (status)
49  {
50  means = std::vector<double>(dimension, 0.0);
51  deviations = std::vector<double>(dimension, 0.0);
52 
53  // Simultaneous computation of means and
54  // means of squared data (useful for variance further computation)
55  std::vector<double> means_of_squares(dimension, 0.0);
56 
57  for (size_t k = 0; k < nb_patterns; ++k)
58  for (size_t d = 0; d < dimension; ++d)
59  {
60  double val = data[k][d];
61 
62  means[d] += val / double(nb_patterns);
63  means_of_squares[d] += Sqr(val) / double(nb_patterns);
64  }
65 
66  // Check means of squared data
67  status = (means_of_squares[0] == means_of_squares[0]);
68 
69  for (size_t d = 1; d < dimension; ++d)
70  status &= (means_of_squares[d] == means_of_squares[d]);
71 
72  std::vector< std::vector<double> > transformed_data(nb_patterns, std::vector<double>(dimension));
73 
74  if (status) // Means for squared data are in legal range
75  {
76  // Deviation computed with König-Huygens formula
77  for (size_t d = 0; d < dimension; ++d)
78  deviations[d] = sqrt(means_of_squares[d] - Sqr(means[d]));
79 
80  // Data patterns centered and reduced
81  for (size_t d = 0; d < dimension; ++d)
82  {
83  double mu = means[d];
84  double sigma = deviations[d];
85 
86  if (sigma != 1.0)
87  for (size_t k = 0; k < nb_patterns; ++k)
88  transformed_data[k][d] = (data[k][d] - mu) / sigma;
89  else
90  for (size_t k = 0; k < nb_patterns; ++k)
91  transformed_data[k][d] = data[k][d] - mu;
92  }
93  }
94  else
95  {
96  // Deviation computed in "classical" way
97  // Data patterns centered simultameously
98  for (size_t d = 0; d < dimension; ++d)
99  {
100  double mu = means[d];
101  double sigma = 0.0;
102 
103  for (size_t k = 0; k < nb_patterns; ++k)
104  {
105  double val = data[k][d];
106 
107  transformed_data[k][d] = val - mu;
108  sigma += Sqr(val - mu) / double(nb_patterns);
109  }
110 
111  sigma = sqrt(sigma);
112  deviations[d] = sigma;
113 
114  if (sigma != 1.0)
115  for (size_t k = 0; k < nb_patterns; ++k)
116  transformed_data[k][d] /= sigma;
117  }
118  }
119 
120  SquareMatrixDouble cmat(MakeCovariance(transformed_data));
121 
122  if (dimension == 2)
123  {
124  if (data_reduction_flag)
125  eigensystem = makeCorrelationSpectralEigensystem(cmat[0][1]);
126  else
127  eigensystem = cmat.MakeSpectralEigensystem();
128  }
129  else
130  eigensystem = cmat.MakeJacobiEigensystem();
131  }
132 }
133 
140 PCA::PCA(const std::vector< std::vector<double> > &data, bool data_reduction_flag)
141 {
142  dimension = data.front().size();
143 
144  size_t nb_patterns = data.size();
145  bool status = ((nb_patterns > 1) && (dimension > 1));
146 
147  for (size_t k = 1; k < nb_patterns; ++k)
148  if (data[k].size() != dimension)
149  {
150  status = false;
151  break;
152  }
153 
154  if (status)
155  {
156  means = std::vector<double>(dimension, 0.0);
157  deviations = std::vector<double>(dimension, 0.0);
158 
159  // Simultaneous computation of means and
160  // means of squared data (useful for variance further computation)
161  std::vector<double> means_of_squares(dimension, 0.0);
162 
163  for (size_t k = 0; k < nb_patterns; ++k)
164  for (size_t d = 0; d < dimension; ++d)
165  {
166  double val = data[k][d];
167 
168  means[d] += val / double(nb_patterns);
169  means_of_squares[d] += Sqr(val) / double(nb_patterns);
170  }
171 
172  // Check means of squared data
173  status = (means_of_squares[0] == means_of_squares[0]);
174 
175  for (size_t d = 1; d < dimension; ++d)
176  status &= (means_of_squares[d] == means_of_squares[d]);
177 
178  std::vector< std::vector<double> > transformed_data(nb_patterns, std::vector<double>(dimension));
179 
180  if (status) // Means for squared data are in legal range
181  {
182  // Deviation computed with König-Huygens formula
183  for (size_t d = 0; d < dimension; ++d)
184  deviations[d] = sqrt(means_of_squares[d] - Sqr(means[d]));
185 
186  // Centered and reduced versions of data patterns
187  for (size_t d = 0; d < dimension; ++d)
188  {
189  double mu = means[d];
190  double sigma = deviations[d];
191 
192  if ((sigma != 1.0) && (sigma != 0.0) && data_reduction_flag)
193  for (size_t k = 0; k < nb_patterns; ++k)
194  transformed_data[k][d] = (data[k][d] - mu) / sigma;
195  else
196  for (size_t k = 0; k < nb_patterns; ++k)
197  transformed_data[k][d] = data[k][d] - mu;
198  }
199  }
200  else
201  {
202  // Deviation computed in "classical" way
203  // Centered data patterns are computed simultameously
204  for (size_t d = 0; d < dimension; ++d)
205  {
206  double mu = means[d];
207  double sigma = 0.0;
208 
209  for (size_t k = 0; k < nb_patterns; ++k)
210  {
211  double val = data[k][d];
212 
213  transformed_data[k][d] = val - mu;
214  sigma += Sqr(val - mu) / double(nb_patterns);
215  }
216 
217  sigma = sqrt(sigma);
218  deviations[d] = sigma;
219 
220  if ((sigma != 1.0) && (sigma != 0.0) && data_reduction_flag)
221  for (size_t k = 0; k < nb_patterns; ++k)
222  transformed_data[k][d] /= sigma;
223  }
224  }
225 
226  SquareMatrixDouble cmat(MakeCovariance(transformed_data));
227 
228  if (dimension == 2)
229  {
230  if (data_reduction_flag)
231  eigensystem = makeCorrelationSpectralEigensystem(cmat[0][1]);
232  else
233  eigensystem = cmat.MakeSpectralEigensystem();
234  }
235  else
236  eigensystem = cmat.MakeJacobiEigensystem();
237  }
238 }
239 
247 PCA::PCA(const std::vector< std::vector<double> > &data, const std::vector<size_t> &cards, bool data_reduction_flag)
248 {
249  dimension = data.front().size();
250 
251  size_t nb_patterns = data.size();
252  double sample_cardinal = 0.0;
253  bool status = ((nb_patterns > 1) && (dimension > 1));
254 
255  for (size_t k = 1; k < nb_patterns; ++k)
256  {
257  if (data[k].size() != dimension)
258  {
259  status = false;
260  break;
261  }
262 
263  sample_cardinal += double(cards[k]);
264  }
265 
266  if (status)
267  {
268  means = std::vector<double>(dimension, 0.0);
269  deviations = std::vector<double>(dimension, 0.0);
270 
271  // Simultaneous computation of means and
272  // means of squared data (useful for variance further computation)
273  std::vector<double> means_of_squares(dimension, 0.0);
274 
275  for (size_t k = 0; k < nb_patterns; ++k)
276  for (size_t d = 0; d < dimension; ++d)
277  {
278  double val = data[k][d];
279  double wgt = double(cards[k]);
280 
281  means[d] += val * wgt / sample_cardinal;
282  means_of_squares[d] += Sqr(val) * wgt / sample_cardinal;
283  }
284 
285  // Check means of squared data
286  status = (means_of_squares[0] == means_of_squares[0]);
287 
288  for (size_t d = 1; d < dimension; ++d)
289  status &= (means_of_squares[d] == means_of_squares[d]);
290 
291  std::vector< std::vector<double> > transformed_data(nb_patterns, std::vector<double>(dimension));
292 
293  if (status) // Means for squared data are in legal range
294  {
295  // Deviation computed with König-Huygens formula
296  for (size_t d = 0; d < dimension; ++d)
297  deviations[d] = sqrt(means_of_squares[d] - Sqr(means[d]));
298 
299  // Data patterns centered and reduced
300  for (size_t d = 0; d < dimension; ++d)
301  {
302  double mu = means[d];
303  double sigma = deviations[d];
304 
305  if (sigma != 1.0)
306  for (size_t k = 0; k < nb_patterns; ++k)
307  transformed_data[k][d] = (data[k][d] - mu) / sigma;
308  else
309  for (size_t k = 0; k < nb_patterns; ++k)
310  transformed_data[k][d] = data[k][d] - mu;
311  }
312  }
313  else
314  {
315  // Deviation computed in "classical" way
316  // Data patterns centered simultameously
317  for (size_t d = 0; d < dimension; ++d)
318  {
319  double mu = means[d];
320  double sigma = 0.0;
321 
322  for (size_t k = 0; k < nb_patterns; ++k)
323  {
324  double val = data[k][d];
325 
326  transformed_data[k][d] = val - mu;
327  sigma += Sqr(val - mu) * double(cards[k]) / sample_cardinal;
328  }
329 
330  sigma = sqrt(sigma);
331  deviations[d] = sigma;
332 
333  if (sigma != 1.0)
334  for (size_t k = 0; k < nb_patterns; ++k)
335  transformed_data[k][d] /= sigma;
336  }
337  }
338 
339  SquareMatrixDouble cmat(MakeCovariance(transformed_data));
340 
341  if (dimension == 2)
342  {
343  if (data_reduction_flag)
344  eigensystem = makeCorrelationSpectralEigensystem(cmat[0][1]);
345  else
346  eigensystem = cmat.MakeSpectralEigensystem();
347  }
348  else
349  eigensystem = cmat.MakeJacobiEigensystem();
350  }
351 }
352 
359 PCA::PCA(const std::map< std::vector<double>, size_t > &data, bool data_reduction_flag)
360 {
361  dimension = data.begin()->first.size();
362 
363  size_t nb_patterns = data.size();
364  double sample_cardinal = 0.0;
365  bool status = ((nb_patterns > 1) && (dimension > 1));
366 
367  for (const auto& weighted_pattern:data)
368  {
369  if (weighted_pattern.first.size() != dimension)
370  {
371  status = false;
372  break;
373  }
374 
375  sample_cardinal += double(weighted_pattern.second);
376  }
377 
378  if (status)
379  {
380  means = std::vector<double>(dimension, 0.0);
381  deviations = std::vector<double>(dimension, 0.0);
382 
383  // Simultaneous computation of means and
384  // means of squared data (useful for variance further computation)
385  std::vector<double> means_of_squares(dimension, 0.0);
386 
387  for (const auto& weighted_pattern:data)
388  for (size_t d = 0; d < dimension; ++d)
389  {
390  double val = weighted_pattern.first[d];
391  double wgt = double(weighted_pattern.second);
392 
393  means[d] += val * wgt / sample_cardinal;
394  means_of_squares[d] += Sqr(val) * wgt / sample_cardinal;
395  }
396 
397  // Check means of squared data
398  status = (means_of_squares[0] == means_of_squares[0]);
399 
400  for (size_t d = 1; d < dimension; ++d)
401  status &= (means_of_squares[d] == means_of_squares[d]);
402 
403  std::vector< std::vector<double> > transformed_data(nb_patterns, std::vector<double>(dimension));
404 
405  if (status) // Means for squared data are in legal range
406  {
407  // Deviation computed with König-Huygens formula
408  for (size_t d = 0; d < dimension; ++d)
409  deviations[d] = sqrt(means_of_squares[d] - Sqr(means[d]));
410 
411  // Data patterns centered and reduced
412  for (size_t d = 0; d < dimension; ++d)
413  {
414  double mu = means[d];
415  double sigma = deviations[d];
416 
417  if (sigma != 1.0)
418  {
419  size_t k = 0;
420 
421  for (const auto& weighted_pattern:data)
422  {
423  transformed_data[k][d] = (weighted_pattern.first[d] - mu) / sigma;
424  ++k;
425  }
426  }
427  else
428  {
429  size_t k = 0;
430 
431  for (const auto& weighted_pattern:data)
432  {
433  transformed_data[k][d] = weighted_pattern.first[d] - mu;
434  ++k;
435  }
436  }
437  }
438  }
439  else
440  {
441  // Deviation computed in "classical" way
442  // Data patterns centered simultameously
443  for (size_t d = 0; d < dimension; ++d)
444  {
445  double mu = means[d];
446  double sigma = 0.0;
447  size_t k = 0;
448 
449  for (const auto& weighted_pattern:data)
450  {
451  double val = weighted_pattern.first[d];
452 
453  transformed_data[k][d] = val - mu;
454  sigma += Sqr(val - mu) * double(weighted_pattern.second) / sample_cardinal;
455  ++k;
456  }
457 
458  sigma = sqrt(sigma);
459  deviations[d] = sigma;
460 
461  if (sigma != 1.0)
462  for (k = 0; k < nb_patterns; ++k)
463  transformed_data[k][d] /= sigma;
464  }
465  }
466 
467  SquareMatrixDouble cmat(MakeCovariance(transformed_data));
468 
469  if (dimension == 2)
470  {
471  if (data_reduction_flag)
472  eigensystem = makeCorrelationSpectralEigensystem(cmat[0][1]);
473  else
474  eigensystem = cmat.MakeSpectralEigensystem();
475  }
476  else
477  eigensystem = cmat.MakeJacobiEigensystem();
478  }
479 
480 }
481 
489 std::multimap<double, MatrixDouble> PCA::makeCorrelationSpectralEigensystem(double g) const
490 {
491  std::multimap<double, MatrixDouble> eigen_pairs;
492 
493  double delta = 4 * g * g;
494 
495  double m_1 = sqrt(delta) / (2 * g);
496 
497  double fraction = 1.0 / sqrt(1.0 + m_1 * m_1);
498 
499  MatrixDouble eigen_vector_1((size_t)2, (size_t)1);
500  MatrixDouble eigen_vector_2((size_t)2, (size_t)1);
501 
502  eigen_vector_1.At(0, 0) = fraction;
503  eigen_vector_1.At(1, 0) = m_1 * fraction;
504 
505  eigen_vector_2.At(0, 0) = - m_1 * fraction;
506  eigen_vector_2.At(1, 0) = fraction;
507 
508  double eigen_value_1 = (2 + sqrt(delta)) / 2.0;
509  double eigen_value_2 = (2 - sqrt(delta)) / 2.0;
510 
511  eigen_pairs.insert(std::make_pair(eigen_value_1, eigen_vector_1));
512  eigen_pairs.insert(std::make_pair(eigen_value_2, eigen_vector_2));
513 
514  return eigen_pairs;
515 }
516 
524 double PCA::GetMean(size_t d) const
525 {
526  if (d >= dimension)
527  throw ExceptionDimension(StringUTF8("PCA::GetMean(size_t d): ") + _("Index out of dimension range."));
528 
529  return means[d];
530 }
531 
539 double PCA::GetDeviation(size_t d) const
540 {
541  if (d >= dimension)
542  throw ExceptionDimension(StringUTF8("PCA::GetMean(size_t d): ") + _("Index out of dimension range."));
543 
544  return deviations[d];
545 }
546 
560 MatrixDouble PCA::Transform(const MatrixDouble &patterns, const size_t nb_features) const
561 {
562  if (patterns.GetCols() != dimension)
563  {
564  throw ExceptionDimension(StringUTF8("PCA::ApplyTransform(const MatrixDouble &patterns, const size_t nb_features): ") + _("Incompatible input pattern dimensions."));
565  }
566  else if (nb_features > dimension)
567  {
568  throw ExceptionDomain(StringUTF8("PCA::ApplyTransform(const MatrixDouble &patterns, const size_t nb_features): ") + _("Incompatible output dimensions."));
569  }
570 
571  size_t nb_patterns = patterns.GetRows();
572  MatrixDouble new_patterns(nb_patterns, nb_features);
573 
574  std::multimap<double, MatrixDouble>::const_reverse_iterator rev_iter;
575 
576  std::vector<double> translated_pattern(dimension);
577 
578  for (size_t p = 0; p < nb_patterns; p++)
579  {
580  for (size_t k = 0; k < dimension; k++)
581  translated_pattern[k] = (patterns[p][k] - means[k]);
582 
583  rev_iter = eigensystem.rbegin();
584 
585  for (size_t f = 0; f < nb_features; f++)
586  {
587  // Scalar product <pattern|eigenvector>
588 
589  double cumul = 0.0;
590  MatrixDouble eigen_vector = rev_iter->second;
591 
592  for (size_t k = 0; k < dimension; ++k)
593  cumul += translated_pattern[k] * eigen_vector[k][0];
594 
595  new_patterns.At(p, f) = cumul;
596  ++rev_iter;
597  }
598  }
599 
600  return new_patterns;
601 }
602 
614 std::vector<std::vector<double>> PCA::Transform(const std::vector< std::vector<double> > &data, const size_t nb_features) const
615 {
616  size_t new_dimension = nb_features;
617 
618  if ((nb_features <= 0) || (nb_features > dimension))
619  new_dimension = dimension;
620 
621  size_t nb_patterns = data.size();
622 
623  std::vector< std::vector<double> > new_patterns(nb_patterns, std::vector<double>(new_dimension));
624 
625  // Reverse iterator to cross the ordered eigensystem
626  std::multimap<double, MatrixDouble>::const_reverse_iterator rev_iter;
627  // A vector to store temporary single translated pattern
628  std::vector<double> translated_pattern(dimension);
629 
630  for (size_t p = 0; p < nb_patterns; ++p)
631  {
632  for (size_t k = 0; k < dimension; ++k)
633  translated_pattern[k] = (data[p][k] - means[k]);
634 
635  rev_iter = eigensystem.rbegin();
636 
637  for (size_t f = 0; f < new_dimension; ++f)
638  {
639  // Scalar product <pattern|eigenvector>
640 
641  double cumul = 0.0;
642  const auto& eigen_vector = rev_iter->second;
643 
644  for (size_t k = 0; k < dimension; ++k)
645  cumul += translated_pattern[k] * eigen_vector[k][0];
646 
647  new_patterns[p][f] = cumul;
648  ++rev_iter;
649  }
650  }
651 
652  return new_patterns;
653 }
654 
663 std::vector<std::vector<double>> PCA::ReverseTransform(const std::vector< std::vector<double> > &data) const
664 {
665  size_t nb_patterns = data.size();
666  std::vector< std::vector<double> > new_patterns;
667  SquareMatrixDouble mat(dimension, 0.0);
668 
669  size_t j = 0;
670 
671  for (auto rev_iter = eigensystem.rbegin(); rev_iter != eigensystem.rend(); ++rev_iter)
672  {
673  MatrixDouble vect = rev_iter->second;
674 
675  for (size_t i = 0; i < dimension; ++i)
676  mat[i][j] = vect[i][0];
677 
678  ++j;
679  }
680 
681  for (size_t p = 0; p < nb_patterns; ++p)
682  {
683  std::vector<double> pattern = data[p];
684  std::vector<double> new_pattern(dimension);
685 
686  for (size_t i = 0; i < dimension; ++i)
687  {
688  double cumul = 0.0;
689 
690  for (size_t k = 0; k < dimension; ++k)
691  cumul += mat[i][k] * pattern[k];
692 
693  new_pattern[i] = cumul + means[i];
694  }
695 
696  new_patterns.push_back(new_pattern);
697  }
698 
699  return new_patterns;
700 }
701 
714 {
715  if (el.GetName() != "PCA")
716  {
717  throw ExceptionInvalidArgument(StringUTF8("bool PCA::deserialize(xml::Element &el): ") +
718  _("Wrong XML element."));
719  }
720 
721  std::multimap<double, MatrixDouble> newsystem;
722 
723  xml::Element sub_el(el.GetFirstChildElement("eigenpair"));
724  while(sub_el)
725  {
726  double w = sub_el.GetAttribute<double>("eigenvalue", false); // may throw
727 
728 
729  xml::Element mat_el(sub_el.GetFirstChildElement("MatrixDouble"));
730  MatrixDouble mat(mat_el); // may throw
731 
732  newsystem.insert(std::make_pair(w, mat));
733 
734  sub_el = sub_el.GetNextSiblingElement("eigenpair");
735  }
736 
737  SMatrixDouble mmat, dmat;
738  sub_el = el.GetFirstChildElement("MatrixDouble");
739  while (sub_el)
740  {
741  StringUTF8 role(sub_el.GetAttribute<StringUTF8>("role"));
742  if (role == "means")
743  mmat = std::make_shared<MatrixDouble>(sub_el); // may throw
744  else if (role == "deviations")
745  dmat = std::make_shared<MatrixDouble>(sub_el); // may throw
746  sub_el = sub_el.GetNextSiblingElement("MatrixDouble");
747  }
748  if (!mmat || !dmat)
749  throw crn::ExceptionNotFound(StringUTF8("bool PCA::deserialize(xml::Element &el): ") + _("Incomplete PCA xml element."));
750 
751  dimension = mmat->GetCols();
752  means = std::vector<double>(dimension);
753  deviations = std::vector<double>(dimension);
754 
755  for (size_t d = 0; d < dimension; ++d)
756  {
757  means[d] = mmat->At(0, d);
758  deviations[d] = dmat->At(0, d);
759  }
760 
761  eigensystem.swap(newsystem);
762 }
763 
774 {
775  xml::Element el(parent.PushBackElement("PCA"));
776  el.SetAttribute("dimension", int(dimension));
777 
778  MatrixDouble mmat(1, dimension);
779  MatrixDouble dmat(1, dimension);
780 
781  for (size_t d = 0; d < dimension; ++d)
782  {
783  mmat.At(0, d) = means[d];
784  dmat.At(0, d) = deviations[d];
785  }
786 
787  xml::Element s(mmat.Serialize(el));
788  s.SetAttribute("role", "means");
789  s = dmat.Serialize(el);
790  s.SetAttribute("role", "deviations");
791 
792  std::multimap<double, MatrixDouble>::const_reverse_iterator rev_iter;
793 
794  for (rev_iter = eigensystem.rbegin(); rev_iter != eigensystem.rend(); ++rev_iter)
795  {
796  xml::Element sub_el(el.PushBackElement("eigenpair"));
797 
798  sub_el.SetAttribute("eigenvalue", rev_iter->first);
799 
800  rev_iter->second.Serialize(sub_el);
801  }
802 
803  return el;
804 }
805 
808  Cloner::Register<PCA>();
810 
size_t GetRows() const noexcept
Returns the number of rows.
Definition: CRNMatrix.h:157
size_t GetCols() const noexcept
Returns the number of columns.
Definition: CRNMatrix.h:163
XML element.
Definition: CRNXml.h:135
StringUTF8 GetName() const
Gets the label of the element.
Definition: CRNXml.h:146
#define _(String)
Definition: CRNi18n.h:51
#define CRN_END_CLASS_CONSTRUCTOR(classname)
Defines a class constructor.
Definition: CRNObject.h:198
PCA(const MatrixDouble &data, bool data_reduction_flag=true)
Constructor.
Definition: CRNPCA.cpp:41
std::multimap< double, MatrixDouble > MakeJacobiEigensystem(size_t MaxIteration=100) const
Perform diagonalization for symmetric matrix.
std::vector< std::vector< double > > MakeCovariance(const std::vector< std::vector< double >> &m)
Return covariance for sample.
MatrixDouble Transform(const MatrixDouble &patterns, size_t nb_features=1u) const
Apply transform to given patterns.
Definition: CRNPCA.cpp:560
A generic domain error.
Definition: CRNException.h:83
void Deserialize(xml::Element &el)
Definition: CRNPCA.cpp:713
virtual xml::Element Serialize(xml::Element &parent) const
Element GetFirstChildElement(const StringUTF8 &name="")
Gets the first child element.
Definition: CRNXml.cpp:320
#define CRN_DATA_FACTORY_REGISTER(elemname, classname)
Registers a class to the data factory.
constexpr SumType< T > Sqr(const T &v) noexcept(noexcept(v *v))
Returns the square of a value.
Definition: CRNMath.h:61
A dimension error.
Definition: CRNException.h:119
void SetAttribute(const StringUTF8 &name, const StringUTF8 &value)
Sets the value of an attribute.
Definition: CRNXml.cpp:595
double GetDeviation(size_t d) const
Returns the deviation of d-th feature computed for sample data.
Definition: CRNPCA.cpp:539
double matrix class
T GetAttribute(const StringUTF8 &name, bool silent=true) const
Gets an attribute.
Definition: CRNXml.h:219
Class to perform Principal Componant Analysis.
Definition: CRNPCA.h:39
std::vector< std::vector< double > > ReverseTransform(const std::vector< std::vector< double > > &data) const
Apply reverse transform to get given patterns' pre-images.
Definition: CRNPCA.cpp:663
const T & At(size_t pos) const noexcept
Definition: CRNMatrix.h:165
Square double matrix class.
std::multimap< double, MatrixDouble > MakeSpectralEigensystem() const
Perform diagonalization for 2x2 symmetric matrix.
xml::Element Serialize(xml::Element &parent) const
Definition: CRNPCA.cpp:773
A character string class.
Definition: CRNStringUTF8.h:49
double GetMean(size_t d) const
Returns the mean value of d-th feature computed for sample data.
Definition: CRNPCA.cpp:524
Element PushBackElement(const StringUTF8 &name)
Adds an element at the end of the children list.
Definition: CRNXml.cpp:355
Invalid argument error (e.g.: nullptr pointer)
Definition: CRNException.h:107
#define CRN_BEGIN_CLASS_CONSTRUCTOR(classname)
Defines a class constructor.
Definition: CRNObject.h:185
An item was not found in a container.
Definition: CRNException.h:95