1 /**
2  * @file methods/kernel_pca/kernel_pca.hpp
3  * @author Ajinkya Kale
4  * @author Marcus Edel
5  *
6  * Defines the KernelPCA class to perform Kernel Principal Components Analysis
7  * on the specified data set.
8  *
9  * mlpack is free software; you may redistribute it and/or modify it under the
10  * terms of the 3-clause BSD license.  You should have received a copy of the
11  * 3-clause BSD license along with mlpack.  If not, see
12  * http://www.opensource.org/licenses/BSD-3-Clause for more information.
13  */
14 #ifndef MLPACK_METHODS_KERNEL_PCA_KERNEL_PCA_HPP
15 #define MLPACK_METHODS_KERNEL_PCA_KERNEL_PCA_HPP
16 
17 #include <mlpack/prereqs.hpp>
18 #include <mlpack/methods/kernel_pca/kernel_rules/naive_method.hpp>
19 
20 namespace mlpack {
21 namespace kpca {
22 
23 /**
24  * This class performs kernel principal components analysis (Kernel PCA), for a
25  * given kernel.  This is a standard machine learning technique and is
26  * well-documented on the Internet and in standard texts.  It is often used as a
27  * dimensionality reduction technique, and can also be useful in mapping
28  * linearly inseparable classes of points to different spaces where they are
29  * linearly separable.
30  *
31  * The performance of the method is highly dependent on the kernel choice.
32  * There are numerous available kernels in the mlpack::kernel namespace (see
33  * files in mlpack/core/kernels/) and it is easy to write your own; see other
34  * implementations for examples.
35  */
36 template <
37   typename KernelType,
38   typename KernelRule = NaiveKernelRule<KernelType>
39 >
40 class KernelPCA
41 {
42  public:
43   /**
44    * Construct the KernelPCA object, optionally passing a kernel.  Optionally,
45    * the transformed data can be centered about the origin; to do this, pass
46    * 'true' for centerTransformedData.  This will take slightly longer (but not
47    * much).
48    *
49    * @param kernel Kernel to be used for computation.
50    * @param centerTransformedData Center transformed data.
51    */
52   KernelPCA(const KernelType kernel = KernelType(),
53             const bool centerTransformedData = false);
54 
55   /**
56    * Apply Kernel Principal Components Analysis to the provided data set.
57    *
58    * @param data Data matrix.
59    * @param transformedData Matrix to output results into.
60    * @param eigval KPCA eigenvalues will be written to this vector.
61    * @param eigvec KPCA eigenvectors will be written to this matrix.
62    * @param newDimension New dimension for the dataset.
63    */
64   void Apply(const arma::mat& data,
65              arma::mat& transformedData,
66              arma::vec& eigval,
67              arma::mat& eigvec,
68              const size_t newDimension);
69 
70   /**
71    * Apply Kernel Principal Components Analysis to the provided data set.
72    *
73    * @param data Data matrix.
74    * @param transformedData Matrix to output results into.
75    * @param eigval KPCA eigenvalues will be written to this vector.
76    * @param eigvec KPCA eigenvectors will be written to this matrix.
77    */
78   void Apply(const arma::mat& data,
79              arma::mat& transformedData,
80              arma::vec& eigval,
81              arma::mat& eigvec);
82 
83   /**
84    * Apply Kernel Principal Component Analysis to the provided data set.
85    *
86    * @param data Data matrix.
87    * @param transformedData Matrix to output results into.
88    * @param eigval KPCA eigenvalues will be written to this vector.
89    */
90   void Apply(const arma::mat& data,
91              arma::mat& transformedData,
92              arma::vec& eigval);
93 
94   /**
95    * Apply dimensionality reduction using Kernel Principal Component Analysis
96    * to the provided data set.  The data matrix will be modified in-place.  Note
97    * that the dimension can be larger than the existing dimension because KPCA
98    * works on the kernel matrix, not the covariance matrix.  This means the new
99    * dimension can be as large as the number of points (columns) in the dataset.
100    * Note that if you specify newDimension to be larger than the current
101    * dimension of the data (the number of rows), then it's not really
102    * "dimensionality reduction"...
103    *
104    * @param data Data matrix.
105    * @param newDimension New dimension for the dataset.
106    */
107   void Apply(arma::mat& data, const size_t newDimension);
108 
109   //! Get the kernel.
Kernel() const110   const KernelType& Kernel() const { return kernel; }
111   //! Modify the kernel.
Kernel()112   KernelType& Kernel() { return kernel; }
113 
114   //! Return whether or not the transformed data is centered.
CenterTransformedData() const115   bool CenterTransformedData() const { return centerTransformedData; }
116   //! Return whether or not the transformed data is centered.
CenterTransformedData()117   bool& CenterTransformedData() { return centerTransformedData; }
118 
119  private:
120   //! The instantiated kernel.
121   KernelType kernel;
122   //! If true, the data will be scaled (by standard deviation) when Apply() is
123   //! run.
124   bool centerTransformedData;
125 }; // class KernelPCA
126 
127 } // namespace kpca
128 } // namespace mlpack
129 
130 // Include implementation.
131 #include "kernel_pca_impl.hpp"
132 
133 #endif // MLPACK_METHODS_KERNEL_PCA_KERNEL_PCA_HPP
134