10 #ifndef FUNCTIONALPCA_H
11 #define FUNCTIONALPCA_H
13 namespace algo::dimred {
21 template<
class T=DTYPE>
22 std::tuple<arma::Col<T>, arma::Mat<T>> ufpca (
const arma::Mat<T>& inputs,
23 const arma::Mat<T>& labels,
24 const bool mean_add =
false )
27 arma::Col<T> eigenvalues;
28 arma::Mat<T> eigenvectors, eigenfunctions;
30 size_t D = inputs.n_rows;
31 size_t N = inputs.n_cols;
32 size_t M = labels.n_rows;
34 assert ( D == 1 &&
"FunctionalData input dim. != 1!");
37 arma::Mat<T> weights(1, N);
39 weights(0,0) = inputs(0,1)-inputs(0,0);
40 weights(0,N-1) = inputs(0,inputs.n_cols-1)-inputs(0,inputs.n_cols-2);
41 weights(0,arma::span(1,N-2)) =
42 inputs(0,arma::span(2,N-1)) - inputs(0,arma::span(0,N-3));
46 arma::Mat<T> sqrt_W = arma::diagmat(arma::sqrt(weights));
47 arma::Mat<T> inv_sqrt_W = arma::diagmat(arma::sqrt(1./weights));
48 arma::Mat<T> mean = arma::mean(labels,0);
49 arma::Mat<T> adj_labels(M, N);
51 for(
size_t i=0; i < M; i++)
52 adj_labels.row(i) = labels.row(i) - mean;
54 arma::Mat<T> covariance = (adj_labels.t() * adj_labels)/(M-1);
56 covariance += covariance.t();
58 arma::Mat<T> variance = sqrt_W * covariance * sqrt_W;
60 arma::eig_sym(eigenvalues, eigenvectors, variance);
61 eigenvalues = eigenvalues.clamp(0., arma::datum::inf);
62 eigenvalues = arma::reverse(eigenvalues);
63 eigenvectors = arma::reverse(eigenvectors,1);
65 eigenfunctions = (inv_sqrt_W*eigenvectors).t();
67 eigenfunctions.each_row() += mean;
68 return std::make_tuple(eigenvalues, eigenfunctions);
78 template<
class T=DTYPE>
79 std::tuple<arma::Col<T>, arma::Mat<T>> ufpca (
const arma::Mat<T>& inputs,
80 const arma::Mat<T>& labels,
83 arma::Col<T> eigenvalues, eigvals;
84 arma::Mat<T> eigenfunctions, eigfuncs;
87 size_t N = inputs.n_cols;
89 auto res = ufpca(inputs, labels);
90 eigenvalues = std::get<0>(res);
91 eigenfunctions = std::get<1>(res);
92 arma::vec cum_ppc= arma::cumsum(eigenvalues) / arma::sum(eigenvalues);
94 arma::uvec cum_ppc_index = arma::find( cum_ppc > ppc, 1);
95 npc = cum_ppc_index[0];
101 eigvals = eigenvalues.subvec(arma::span(0,npc-1));
102 eigfuncs = eigenfunctions(arma::span(0,npc-1),arma::span(0,N-1));
104 return std::make_tuple(eigvals, eigfuncs);
114 template<
class T=DTYPE>
115 std::tuple<arma::Col<T>, arma::Mat<T>> ufpca (
const arma::Mat<T>& inputs,
116 const arma::Mat<T>& labels,
120 arma::Col<T> eigenvalues, eigvals;
121 arma::Mat<T> eigenfunctions, eigfuncs;
123 size_t N = inputs.n_cols;
125 auto res = ufpca(inputs, labels);
127 eigenvalues = std::get<0>(res);
128 eigenfunctions = std::get<1>(res);
130 eigvals = eigenvalues.subvec(arma::span(0,npc-1));
131 eigfuncs = eigenfunctions(arma::span(0,npc-1),arma::span(0,N-1));
133 return std::make_tuple(eigvals, eigfuncs);