Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
PCA.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 #include <MathAlgo/PCA.hh>
26 #include <MathAlgo/SVD.hh>
27 #include <Base/Common/BIASpragma.hh>
28 
29 using namespace BIAS;
30 using namespace std;
31 
32 
33 void PCA::ComputeReductionMatrix(const vector<vector<Vector<PCAType> > >& vec,
34  BIAS::Matrix<PCAType> &matrix,
35  int reductionSize){
36  int counter = 0;
37  for (unsigned int i=0; i<vec.size(); i++) {
38  counter += vec[i].size();
39  }
40  vector<Vector<PCAType> > newvec;
41  newvec.reserve(counter);
42  for (unsigned int i=0; i<vec.size(); i++) {
43  const vector<Vector<PCAType> > &partvec = vec[i];
44  for (unsigned int j=0; j<partvec.size(); j++) {
45  newvec.push_back(partvec[j]);
46  }
47  }
48  ComputeReductionMatrix(newvec, matrix, reductionSize);
49 
50 }
51 
53  BIAS::Matrix<PCAType> &matrix,
54  int reductionSize){
55  if (reductionSize==-1) reductionSize = reductionSize_;
56  BIASASSERT(reductionSize>0);
57 
58  const int dimensions=vec[0].size();
59 
60 
61  //covariance-matrix and matrix U,V,S for SVD
62  Matrix<PCAType> cov(dimensions, dimensions, 0.0f);
63 
64  //compute mean
65  ComputeMean(vec, mean_);
66  ComputeScatter(vec, mean_, cov);
67  ComputeReductionMatrix(cov, matrix, false, reductionSize);
68 }
69 
70 
71 
73  BIAS::Matrix<PCAType> &matrix,
74  bool normalize,
75  int reductionSize){
76  if (reductionSize==-1) reductionSize = reductionSize_;
77  BIASASSERT(reductionSize>0);
78  BIASASSERT(cov.num_rows() == cov.num_cols());
79 
80  Matrix<double> covd(cov.num_rows(), cov.num_cols(), 0.0);
81  for (int i=0; i<cov.num_cols(); i++){
82  for (int j=0; j<=i; j++){
83  // make symmetric (scale by 2 does not matter)
84  covd[i][j] = covd[j][i] = double( cov[j][i] ) + double( cov[i][j] ) ;
85  }
86  }
87 
88  Matrix<double> U,V;
89  //make SVD
90  SVD svd(covd);
91  S_ = svd.GetS();
92  U = svd.GetVT();
93 
94  // if rows are normalize we should use mahalanobis distance in transformed
95  // space instead of norm2, so do not normalize here ...
96  if (normalize) U.NormalizeRows();
97 
98  matrix.newsize(cov.num_rows(), reductionSize);
99  for (int i=0;i<matrix.num_cols();i++){
100  for (int j=0;j<matrix.num_rows();j++){
101  matrix[j][i]= PCAType( U[i][j] );//<1.0e-13?0.0f:U[j][i];
102  }
103  }
104 
105 }
106 
108  const BIAS::Vector<PCAType> &mean,
109  BIAS::Matrix<PCAType> &cov) {
110  // compute covariance matrix
111  for (int k=0; k<(int)vec.size(); k++){
112  const BIAS::Vector<PCAType>& veck = vec[k];
113  for (int i=0; i<veck.size(); i++){
114  const PCAType &vecki = veck[i];
115  for (int j=0; j<=i; j++){
116  cov[i][j] += (vecki-mean[i]) * (veck[j]-mean[j]);
117  }
118  }
119  }
120  for (int i=0; i<cov.num_rows(); i++){
121  for (int j=i+1; j<cov.num_cols(); j++){
122  cov[i][j] = cov[j][i];
123  }
124  }
125 }
126 
127 void PCA::ComputeMean(const vector<BIAS::Vector<PCAType> > &vec,
128  BIAS::Vector<PCAType> &mean){
129  BIASASSERT(!vec.empty());
130  // sum up
131  mean.newsize(vec[0].size());
132  mean.SetZero();
133  for (int k=0; k<(int)vec.size(); k++){
134  const BIAS::Vector<PCAType>& veck = vec[k];
135  for (int i=0; i<veck.size(); i++){
136  mean[i] += veck[i];
137  }
138  }
139  // divide
140  const PCAType vecsize = 1.0f / PCAType(vec.size());
141  for (int i=0; i<mean.size(); i++){
142  mean[i] *= vecsize;
143  }
144 }
145 
146 void PCA::SetReductionSize(int size){
147  reductionSize_ = size;
148 }
149 
151  mean = mean_;
152 }
void ComputeScatter(const std::vector< BIAS::Vector< PCAType > > &vec, const BIAS::Vector< PCAType > &mean, BIAS::Matrix< PCAType > &cov)
compute unnomalized covariance
Definition: PCA.cpp:107
computes and holds the singular value decomposition of a rectangular (not necessarily quadratic) Matr...
Definition: SVD.hh:92
Subscript num_cols() const
Definition: cmat.h:320
void SetReductionSize(int size)
Definition: PCA.cpp:146
Matrix< T > & newsize(Subscript M, Subscript N)
Definition: cmat.h:269
void SetZero()
equivalent to matrix call
Definition: Vector.hh:156
Vector< T > & newsize(Subscript N)
Definition: vec.h:220
void GetMean(BIAS::Vector< PCAType > &mean)
get mean of a vector
Definition: PCA.cpp:150
const Matrix< double > & GetVT() const
return VT (=transposed(V))
Definition: SVD.hh:177
const Vector< double > & GetS() const
return S which is a vector of the singular values of A in descending order.
Definition: SVD.hh:167
matrix class with arbitrary size, indexing is row major.
void ComputeReductionMatrix(const std::vector< BIAS::Vector< PCAType > > &vec, BIAS::Matrix< PCAType > &matrix, int reductionSize=-1)
Computes a reduction-matrix.
Definition: PCA.cpp:52
Subscript num_rows() const
Definition: cmat.h:319
void ComputeMean(const std::vector< BIAS::Vector< PCAType > > &vec, BIAS::Vector< PCAType > &mean)
computes mean of a set of vectors
Definition: PCA.cpp:127
void NormalizeRows()
Normalizes each row to L2 norm one.
Definition: Matrix.cpp:178
Subscript size() const
Definition: vec.h:262