naive_method.hpp
Go to the documentation of this file.
1 
13 #ifndef MLPACK_METHODS_KERNEL_PCA_NAIVE_METHOD_HPP
14 #define MLPACK_METHODS_KERNEL_PCA_NAIVE_METHOD_HPP
15 
16 #include <mlpack/prereqs.hpp>
17 
18 namespace mlpack {
19 namespace kpca {
20 
21 template<typename KernelType>
23 {
24  public:
35  static void ApplyKernelMatrix(const arma::mat& data,
36  arma::mat& transformedData,
37  arma::vec& eigval,
38  arma::mat& eigvec,
39  const size_t /* rank */,
40  KernelType kernel = KernelType())
41 {
42  // Construct the kernel matrix.
43  arma::mat kernelMatrix;
44  // Resize the kernel matrix to the right size.
45  kernelMatrix.set_size(data.n_cols, data.n_cols);
46 
47  // Note that we only need to calculate the upper triangular part of the
48  // kernel matrix, since it is symmetric. This helps minimize the number of
49  // kernel evaluations.
50  for (size_t i = 0; i < data.n_cols; ++i)
51  {
52  for (size_t j = i; j < data.n_cols; ++j)
53  {
54  // Evaluate the kernel on these two points.
55  kernelMatrix(i, j) = kernel.Evaluate(data.unsafe_col(i),
56  data.unsafe_col(j));
57  }
58  }
59 
60  // Copy to the lower triangular part of the matrix.
61  for (size_t i = 1; i < data.n_cols; ++i)
62  for (size_t j = 0; j < i; ++j)
63  kernelMatrix(i, j) = kernelMatrix(j, i);
64 
65  // For PCA the data has to be centered, even if the data is centered. But it
66  // is not guaranteed that the data, when mapped to the kernel space, is also
67  // centered. Since we actually never work in the feature space we cannot
68  // center the data. So, we perform a "psuedo-centering" using the kernel
69  // matrix.
70  arma::rowvec rowMean = arma::sum(kernelMatrix, 0) / kernelMatrix.n_cols;
71  kernelMatrix.each_col() -= arma::sum(kernelMatrix, 1) / kernelMatrix.n_cols;
72  kernelMatrix.each_row() -= rowMean;
73  kernelMatrix += arma::sum(rowMean) / kernelMatrix.n_cols;
74 
75  // Eigendecompose the centered kernel matrix.
76  kernelMatrix = arma::symmatu(kernelMatrix);
77  if (!arma::eig_sym(eigval, eigvec, kernelMatrix))
78  {
79  Log::Fatal << "Failed to construct the kernel matrix." << std::endl;
80  }
81 
82  // Swap the eigenvalues since they are ordered backwards (we need largest to
83  // smallest).
84  for (size_t i = 0; i < floor(eigval.n_elem / 2.0); ++i)
85  eigval.swap_rows(i, (eigval.n_elem - 1) - i);
86 
87  // Flip the coefficients to produce the same effect.
88  eigvec = arma::fliplr(eigvec);
89 
90  transformedData = eigvec.t() * kernelMatrix;
91  transformedData.each_col() /= arma::sqrt(eigval);
92 }
93 };
94 
95 } // namespace kpca
96 } // namespace mlpack
97 
98 #endif
Linear algebra utility functions, generally performed on matrices or vectors.
static void ApplyKernelMatrix(const arma::mat &data, arma::mat &transformedData, arma::vec &eigval, arma::mat &eigvec, const size_t, KernelType kernel=KernelType())
Construct the exact kernel matrix.
The core includes that mlpack expects; standard C++ includes, Armadillo, cereal, and a few basic mlpa...
constexpr auto data(Container const &container) noexcept -> decltype(container.data())
Definition: iterator.hpp:79
static util::PrefixedOutStream Fatal
Definition: log.hpp:105