the lastest pca lib by Castle
Dependents: the-lastest-code mbed-test-i2c-PCA-biquad-peakdet
pca.cpp@0:8670ef66c0e3, 2019-11-25 (annotated)
- Committer:
- castlefei
- Date:
- Mon Nov 25 14:26:29 2019 +0000
- Revision:
- 0:8670ef66c0e3
PCA lib by Castle; ;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
castlefei | 0:8670ef66c0e3 | 1 | |
castlefei | 0:8670ef66c0e3 | 2 | #include "pca.h" |
castlefei | 0:8670ef66c0e3 | 3 | #include <Eigen/Dense.h> |
castlefei | 0:8670ef66c0e3 | 4 | |
castlefei | 0:8670ef66c0e3 | 5 | using namespace Eigen; |
castlefei | 0:8670ef66c0e3 | 6 | |
castlefei | 0:8670ef66c0e3 | 7 | /* |
castlefei | 0:8670ef66c0e3 | 8 | * Normalize the Matrix X |
castlefei | 0:8670ef66c0e3 | 9 | */ |
castlefei | 0:8670ef66c0e3 | 10 | MatrixXd PCA::featurnormail(MatrixXd &X) |
castlefei | 0:8670ef66c0e3 | 11 | { |
castlefei | 0:8670ef66c0e3 | 12 | //I don't know why to use the transpose |
castlefei | 0:8670ef66c0e3 | 13 | //compute the mean of every dimension |
castlefei | 0:8670ef66c0e3 | 14 | MatrixXd X1 = X.transpose(); |
castlefei | 0:8670ef66c0e3 | 15 | MatrixXd meanval = X1.colwise().mean(); |
castlefei | 0:8670ef66c0e3 | 16 | |
castlefei | 0:8670ef66c0e3 | 17 | //normalization |
castlefei | 0:8670ef66c0e3 | 18 | RowVectorXd meanvecRow = meanval; |
castlefei | 0:8670ef66c0e3 | 19 | X1.rowwise() -= meanvecRow; |
castlefei | 0:8670ef66c0e3 | 20 | |
castlefei | 0:8670ef66c0e3 | 21 | return X1.transpose(); |
castlefei | 0:8670ef66c0e3 | 22 | } |
castlefei | 0:8670ef66c0e3 | 23 | |
castlefei | 0:8670ef66c0e3 | 24 | /* |
castlefei | 0:8670ef66c0e3 | 25 | * Compute the Covariane Matrix of X, put to C |
castlefei | 0:8670ef66c0e3 | 26 | * C = 1/m * X * X.transpose |
castlefei | 0:8670ef66c0e3 | 27 | */ |
castlefei | 0:8670ef66c0e3 | 28 | void PCA::ComComputeCov(MatrixXd &X, MatrixXd &C) |
castlefei | 0:8670ef66c0e3 | 29 | { |
castlefei | 0:8670ef66c0e3 | 30 | |
castlefei | 0:8670ef66c0e3 | 31 | C = X*X.adjoint();//same as XT*X a |
castlefei | 0:8670ef66c0e3 | 32 | //translate to array |
castlefei | 0:8670ef66c0e3 | 33 | C = C.array() / X.cols(); |
castlefei | 0:8670ef66c0e3 | 34 | } |
castlefei | 0:8670ef66c0e3 | 35 | |
castlefei | 0:8670ef66c0e3 | 36 | |
castlefei | 0:8670ef66c0e3 | 37 | /* |
castlefei | 0:8670ef66c0e3 | 38 | * Compute the eigenvalue and eigenvector of C |
castlefei | 0:8670ef66c0e3 | 39 | * val = (first eigenvalue) --smallest --not important |
castlefei | 0:8670ef66c0e3 | 40 | * . |
castlefei | 0:8670ef66c0e3 | 41 | * . |
castlefei | 0:8670ef66c0e3 | 42 | * . |
castlefei | 0:8670ef66c0e3 | 43 | * (last eigenvalue) --largest -- important |
castlefei | 0:8670ef66c0e3 | 44 | * |
castlefei | 0:8670ef66c0e3 | 45 | * vec = (first eigenvector, ... , last eigenvector) |
castlefei | 0:8670ef66c0e3 | 46 | * not important important |
castlefei | 0:8670ef66c0e3 | 47 | */ |
castlefei | 0:8670ef66c0e3 | 48 | void PCA::ComputEig(MatrixXd &C, MatrixXd &vec, MatrixXd &val) |
castlefei | 0:8670ef66c0e3 | 49 | { |
castlefei | 0:8670ef66c0e3 | 50 | //SelfAdjointEigenSolver will sort the values automatically |
castlefei | 0:8670ef66c0e3 | 51 | SelfAdjointEigenSolver<MatrixXd> eig(C); |
castlefei | 0:8670ef66c0e3 | 52 | vec = eig.eigenvectors(); |
castlefei | 0:8670ef66c0e3 | 53 | val = eig.eigenvalues(); |
castlefei | 0:8670ef66c0e3 | 54 | } |
castlefei | 0:8670ef66c0e3 | 55 | |
castlefei | 0:8670ef66c0e3 | 56 | /* Compute the dimension need to include enough information of raw data. |
castlefei | 0:8670ef66c0e3 | 57 | * form large index to small index, since the val is sorted from small to large. |
castlefei | 0:8670ef66c0e3 | 58 | * in some cases, just decide the number of dimension, instead of compute it. |
castlefei | 0:8670ef66c0e3 | 59 | */ |
castlefei | 0:8670ef66c0e3 | 60 | int PCA::ComputDim(MatrixXd &val) |
castlefei | 0:8670ef66c0e3 | 61 | { |
castlefei | 0:8670ef66c0e3 | 62 | int dim; |
castlefei | 0:8670ef66c0e3 | 63 | double sum = 0; |
castlefei | 0:8670ef66c0e3 | 64 | for (int i = val.rows() - 1; i >= 0;--i) |
castlefei | 0:8670ef66c0e3 | 65 | { |
castlefei | 0:8670ef66c0e3 | 66 | sum += val(i, 0); |
castlefei | 0:8670ef66c0e3 | 67 | dim = i; |
castlefei | 0:8670ef66c0e3 | 68 | if (sum / val.sum()>=0.8)//80% of the information |
castlefei | 0:8670ef66c0e3 | 69 | break; |
castlefei | 0:8670ef66c0e3 | 70 | } |
castlefei | 0:8670ef66c0e3 | 71 | return val.rows() - dim; |
castlefei | 0:8670ef66c0e3 | 72 | } |