00001
00002
00003
00004
00005
00006 #ifndef PCA_TOOL_H
00007 #define PCA_TOOL_H
00008
00009 #include <iostream>
00010 #include <cmath>
00011 #include "object.h"
00012
00013 namespace mimas {
00021 class pca_tool: public object
00022 {
00023 private:
00024 matrix_tool scores, loadings, variances;
00025 bool pca_performed;
00026
00027 public:
00028 pca_tool(void);
00029 void pca(matrix_tool& X);
00030 void project(matrix_tool& Y, int n);
00031 };
00032
00033 pca_tool::pca_tool(void)
00034 {
00035 pca_performed=false;
00036 }
00037
00038 void pca_tool::pca(matrix_tool& X)
00039 {
00040 matrix_tool u, d, v, centeredX;
00041
00042 MMERROR( X.initialised(), exception, ,
00043 "pca_tool::pca - input matrix not initialised" );
00044
00045 centeredX=X;
00046
00047
00048 for (int j=0; j<centeredX.getCols(); j++)
00049 {
00050 double mean=0.0;
00051
00052 for (int i=0; i<centeredX.getRows(); i++)
00053 mean+=centeredX(i,j);
00054
00055 mean/=centeredX.getRows();
00056
00057 for (int i=0; i<centeredX.getRows(); i++)
00058 centeredX(i,j)=centeredX(i,j)-mean;
00059
00060 }
00061
00062 centeredX.svd(u,d,loadings);
00063
00064 scores=u*d;
00065
00066 variances.redim(d.getCols(),1);
00067 for(int i=0; i<d.getCols(); i++)
00068 variances(i,0)=d(i,i);
00069
00070 pca_performed=true;
00071
00072 }
00073
00074 void pca_tool::project(matrix_tool& Y, int n)
00075 {
00076 if (!pca_performed) return;
00077
00078 MMERROR( n>=0 && n<loadings.getCols(), exception, ,
00079 "pca_tool::reduce - number of components out of range" );
00080
00081 Y.redim(scores.getRows(),loadings.getRows());
00082
00083 matrix_tool t,p;
00084
00085 t.redim(scores.getRows(),n);
00086
00087 for (int i=0; i<scores.getRows(); i++)
00088 for (int j=0; j<n; j++)
00089 t(i,j)=scores(i,j);
00090
00091 p.redim(loadings.getRows(),n);
00092
00093 for (int i=0; i<loadings.getRows(); i++)
00094 for (int j=0; j<n; j++)
00095 p(i,j)=loadings(i,j);
00096
00097
00098 p.save("p.dat");
00099 t.save("t.dat");
00100
00101 p.transpose();
00102
00103 Y=t*p;
00104
00105 }
00106 }
00107
00108 #endif
00109
00110