LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiKPCA.h

00001 /*
00002  * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 
00024 /*----------------------------------------------------------------
00025  * project ....: LTI Digital Image/Signal Processing Library
00026  * file .......: ltiKPCA.h
00027  * authors ....: Pablo Alvarado Jochen Wickel
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 27.11.2000
00030  * revisions ..: $Id: ltiKPCA.h,v 1.9 2006/02/08 12:28:10 ltilib Exp $
00031  */
00032 
00033 #ifndef _LTI_K_P_C_A_H_
00034 #define _LTI_K_P_C_A_H_
00035 
00036 #include "ltiPCA.h"
00037 #include "ltiEigenSystem.h"
00038 #include "ltiIoHandler.h"
00039 #include "ltiKernelFunctor.h"
00040 #include "ltiObjectFactory.h"
00041 
00042 namespace lti {
00043   /**
00044    * Functor for computing a kernel principal component analysis.
00045    *
00046    * It receives a set of input vectors in form of a matrix (each row of
00047    * the matrix corresponds to an input vector), which will be transformed
00048    * with KPCA.
00049    *
00050    * The first time you use the apply()-method, the transformation
00051    * matrix will be computed.  You can use this transformation matrix
00052    * with other data sets using the transform() methods.
00053    *
00054    * Please note that the eigenvector matrices will contain the
00055    * eigenvector in the COLUMNS and not in the rows, as could be
00056    * expected.  This avoids the requirement of transposing matrices in
00057    * the vector transformations (see also lti::eigenSystem<T>).
00058    *
00059    * The Kernel PCA is described in Schoelkopf, B., Smola, A. and
00060    * Mueller, K. "Nonlinear Component Analysis as a Kernel Eigenvalue
00061    * Problem", Neural Computation, vol. 10, no. 5, pp. 1299-1319
00062    */
00063   class kernelPCA: public linearAlgebraFunctor {
00064   public:
00065     /**
00066      * the parameters for the class principalComponents
00067      */
00068     class parameters : public linearAlgebraFunctor::parameters {
00069     public:
00070 
00071       /**
00072        * default constructor
00073        */
00074       parameters();
00075 
00076       /**
00077        * copy constructor
00078        * @param other the parameters object to be copied
00079        */
00080       parameters(const parameters& other);
00081 
00082       /**
00083        * destructor
00084        */
00085       ~parameters();
00086 
00087       /**
00088        * returns name of this type
00089        */
00090       const char* getTypeName() const;
00091 
00092       /**
00093        * copy the contents of a parameters object
00094        * @param other the parameters object to be copied
00095        * @return a reference to this parameters object
00096        */
00097       parameters& copy(const parameters& other);
00098 
00099       /**
00100        * Assigns the contents of the other object to this object
00101        */
00102       inline parameters& operator=(const parameters& other);
00103 
00104       /**
00105        * returns a pointer to a clone of the parameters
00106        */
00107       virtual functor::parameters* clone() const;
00108 
00109       /**
00110        * write the parameters in the given ioHandler
00111        * @param handler the ioHandler to be used
00112        * @param complete if true (the default) the enclosing begin/end will
00113        *        be also written, otherwise only the data block will be written.
00114        * @return true if write was successful
00115        */
00116       virtual bool write(ioHandler& handler,const bool complete=true) const;
00117 
00118       /**
00119        * read the parameters from the given ioHandler
00120        * @param handler the ioHandler to be used
00121        * @param complete if true (the default) the enclosing begin/end will
00122        *        be also written, otherwise only the data block will be written.
00123        * @return true if write was successful
00124        */
00125       virtual bool read(ioHandler& handler,const bool complete=true);
00126 
00127 #     ifdef _LTI_MSC_6
00128       /**
00129        * this function is required by MSVC only, as a workaround for a
00130        * very awful bug, which exists since MSVC V.4.0, and still by
00131        * V.6.0 with all bugfixes (so called "service packs") remains
00132        * there...  This method is also public due to another bug, so please
00133        * NEVER EVER call this method directly: use read() instead
00134        */
00135       bool readMS(ioHandler& handler,const bool complete=true);
00136 
00137       /**
00138        * this function is required by MSVC only, as a workaround for a
00139        * very awful bug, which exists since MSVC V.4.0, and still by
00140        * V.6.0 with all bugfixes (so called "service packs") remains
00141        * there...  This method is also public due to another bug, so please
00142        * NEVER EVER call this method directly: use write() instead
00143        */
00144       bool writeMS(ioHandler& handler,const bool complete=true) const;
00145 #     endif
00146 
00147       /**
00148        * Sets a new kernel function.  A copy of the kernel will be
00149        * done (so it is useless to change the parameters of the given
00150        * kernel instance, because the internal kernel will never
00151        * notice the changes done to its "parent").
00152        */
00153       void setKernel(const kernelFunctor<double>& k);
00154 
00155       /**
00156        * Sets a new kernel function. The kernel which is passed here as an
00157        * argument must have been allocated with new; it must not be
00158        * a local variable. On destruction of the parameters object,
00159        * the kernel will be deleted, i.e. this parameters instance will be
00160        * responsible for the memory managment of the object.
00161        */
00162       void attachKernel(kernelFunctor<double>* k);
00163 
00164       /**
00165        * Sets a new kernel function. The kernel which is passed here as an
00166        * argument is not deleted by the parameters object, the caller
00167        * must ensure that there are no memory leaks.
00168        */
00169       void useExternalKernel(kernelFunctor<double>* k);
00170 
00171       /**
00172        * create a new kernel function, using its class name. A pointer to the
00173        * kernel function is returned, so that the caller may modify
00174        * the kernel's parameters.
00175        */
00176       kernelFunctor<double>* createKernel(const std::string& name) const;
00177 
00178       // ------------------------------------------------
00179       // the parameters
00180       // ------------------------------------------------
00181 
00182       /**
00183        * The kernel function.  Try to use the kernel setting methods in order
00184        * to ensure a consistent memory managment of the pointed instance.
00185        * @see setKernel(),attachKernel(),useExternalKernel()
00186        *
00187        * Default value: "linearKernel"
00188        */
00189       kernelFunctor<double>* kernel;
00190 
00191       /**
00192        * This is the maximal dimension of the reduced vectors.
00193        *
00194        * Default value: 3
00195        */
00196       int resultDim;
00197 
00198       /**
00199        * This flag determines, if the functor should determine a
00200        * maximum allowable dimension itself. "Maximum dimension" means
00201        * that the dimension is equal to the number of eigenvalues of
00202        * the covariance matrix which are larger than zero.
00203        *
00204        * Default value: false
00205        */
00206       bool autoDim;
00207 
00208       /**
00209        * The eigensystem functor used for computing eigenvectors.
00210        *
00211        * Default value: lti::jacobi<double>
00212        */
00213       eigenSystem<double> *eigen;
00214 
00215       /**
00216        * This flag determines if the functor should perform a
00217        * whitening transform of the data. Whitening means that
00218        * 1. A KPCA is performed
00219        * 2. A scaling of the transformed data by the inverse of the
00220        *    square root of the eigenvalues.
00221        *
00222        * The default is false.
00223        */
00224       bool whitening;
00225 
00226 
00227       /**
00228        * The factor which determines relevant eigenvectors. An eigenvector
00229        * is considered relevant if its eigenvalue is at least as large
00230        * as the largest eigenvalue divided by this number. Usually,
00231        * it takes values between 1e4 and 1e6.
00232        */
00233       double relevance;
00234 
00235     private:
00236       /**
00237        * array of objects needed by the functor factory
00238        */
00239       static const kernelFunctor<double>* kernelArray[];
00240 
00241       /**
00242        * kernel functor factory
00243        */
00244       static objectFactory< kernelFunctor<double> > kfa;
00245 
00246       /**
00247        * class name object used to detect the type name of an object instance.
00248        */
00249       className cn;
00250 
00251       /**
00252        * Flag used to inidicate if the local kernel functor must be deleted
00253        * by this object or not (just pointing to some external instance...)
00254        */
00255       bool destroyKernel;
00256 
00257     };
00258 
00259     /**
00260      * default constructor
00261      */
00262     kernelPCA();
00263 
00264     /**
00265      * copy constructor
00266      * @param other the object to be copied
00267      */
00268     kernelPCA(const kernelPCA& other);
00269 
00270     /**
00271      * destructor
00272      */
00273     virtual ~kernelPCA();
00274 
00275     /**
00276      * returns the name of this type ("kernelPCA")
00277      */
00278     virtual const char* getTypeName() const;
00279 
00280     /**
00281      * Computes the principal components of the data matrix
00282      * and transforms it according to the new coordinate system.
00283      * The result is the transformed matrix.
00284      * data and result must not be references to the same matrix.
00285      * This method uses the eigenvector functor given in the parameters.
00286      * By default, it uses ltilib's own jacobi functor. However, you can
00287      * speed it up considerably by using the eigensystem functor in
00288      * the lamath directory.
00289      *
00290      * If you don't need to transform the input data, and just want to
00291      * use the input matrix to compute the principal components you
00292      * can use the method computeTransformMatrix().  If you just need
00293      * to transform the data, without computing the transformation matrix, you
00294      * can use the method transform().
00295      *
00296      * @param data dmatrix with the source data.
00297      * @param result dmatrix with the result data.
00298      * @return true if the KPCA could be computed, false otherwise
00299      */
00300     virtual bool apply(const dmatrix& data, dmatrix& result);
00301 
00302     /**
00303      * On-Place version of the transformation.
00304      *
00305      * If you don't need to transform the input data, and just want to
00306      * use the input matrix to compute the principal components you
00307      * can use the method computeTransformMatrix().  If you just need
00308      * to transform the data, without computing the transformation matrix, you
00309      * can use the method transform().
00310      *
00311      * @param srcdest dmatrix with the source data, which will also contain
00312      *        the result.
00313      * @return a reference to <code>srcdest</code>.
00314      */
00315     virtual bool apply(dmatrix& srcdest);
00316 
00317     /**
00318      * Transforms a single vector according to a previously computed
00319      * transformation matrix. (this is an alias for the transform() method)
00320      */
00321     inline bool apply(const dvector &src, dvector& result) {
00322       return transform(src,result);
00323     }
00324 
00325     /**
00326      * Transforms a single vector according to a previously computed
00327      * transformation matrix.
00328      * @param src the data vector
00329      * @param result the vector which will receive the transformed data
00330      * @return a reference to <code>result</code>
00331      */
00332     virtual bool transform(const dvector &src, dvector& result) const;
00333 
00334     /**
00335      * Transform an entire matrix according to a previously computed
00336      * transformation matrix. Unfortunately, we must choose a name
00337      * different from apply.
00338      * @param src the data matrix
00339      * @param result the matrix which will receive the transformed data
00340      * @return true if successful, false otherwise.
00341      */
00342     virtual bool transform(const dmatrix &src, dmatrix& result) const;
00343 
00344     /**
00345      * Transform an entire matrix according to a previously computed
00346      * transformation matrix. Unfortunately, we must choose a name
00347      * different from apply.
00348      * @param srcdest the data matrix.  The result will be left here too.
00349      * @return true if successful, false otherwise.
00350      */
00351     virtual bool transform(dmatrix &srcdest) const;
00352 
00353     /**
00354      * Compute the transformation matrix.  Similar to the apply() method,
00355      * but it does not transform the given data (this saves some time).
00356      *
00357      * @param src the matrix with the input data to be analysed.
00358      * @return true if transformation matrix could be computed, false otherwise
00359      */
00360     virtual bool computeTransformMatrix(const dmatrix& src);
00361 
00362     /**
00363      * Alias for computeTransformMatrix()
00364      */
00365     virtual bool train(const dmatrix& src);
00366 
00367     /**
00368      * Returns the previously computed eigenvalues of the covariance
00369      * matrix.
00370      * @param result the vector which will receive the eigenvalues.
00371      * @return true if the values could be obtained, false otherwise.
00372      */
00373     virtual bool getEigenValues(dvector& result) const;
00374 
00375     /**
00376      * Returns the previously computed eigenvalues of the covariance
00377      * matrix.
00378      *
00379      * @return a const reference to the last computed eigenvalues
00380      */
00381     virtual const dvector& getEigenValues() const;
00382 
00383     /**
00384      * Returns the previously computed eigenvectors of the covariance
00385      * matrix.  Each ROW (as opposite to PCA) will contain the eigenvectors.
00386      *
00387      * @param result the matrix which will receive the eigenvectors.
00388      *        Each row of the matrix contains one eigenvector.
00389      * @return true if the vectors could be obtained, false otherwise
00390      */
00391     virtual bool getEigenVectors(dmatrix& result) const;
00392 
00393     /**
00394      * Returns the previously computed eigenvectors of the covariance
00395      * matrix.
00396      * @return a const reference to the last computed eigenvectors.
00397      *         Each row of the matrix contains one eigenvector.
00398      */
00399     virtual const dmatrix& getEigenVectors() const;
00400 
00401     /**
00402      * Set the dimension to which the vectors should be reduced.
00403      */
00404     virtual void setDimension(int k);
00405 
00406     /**
00407      * copy data of "other" functor.
00408      * @param other the functor to be copied
00409      * @return a reference to this functor object
00410      */
00411     kernelPCA& copy(const kernelPCA& other);
00412 
00413     /**
00414      * returns a pointer to a clone of this functor.
00415      */
00416     virtual functor* clone() const;
00417 
00418     /**
00419      * returns used parameters
00420      */
00421     const parameters& getParameters() const;
00422 
00423     /**
00424      * set functor's parameters.
00425      * This member makes a copy of <em>theParam</em>: the functor
00426      * will keep its own copy of the parameters!
00427      * @return true if successful, false otherwise
00428      */
00429     virtual bool updateParameters();
00430 
00431     /**
00432      * Reads this functor from the given handler.
00433      */
00434     virtual bool read(ioHandler &handler, const bool complete=true);
00435 
00436     /**
00437      * Writes this functor to the given handler.
00438      */
00439     virtual bool write(ioHandler &handler, const bool complete=true) const;
00440 
00441     /**
00442      * Number of dimensions considered in the transformation
00443      * @return the number of dimensions used for the transformation.  It
00444      *         is always less or equal the number of dimensions of the input
00445      *         vectors.
00446      */
00447     int getUsedDimension() const {
00448       return usedDimensionality;
00449     }
00450 
00451   protected:
00452     /**
00453      * Determines the intrinsic dimensionality of the data set if the
00454      * user specify autoDim, otherwise return parameters::resultDim.
00455      * The member usedDimensionality will be set with the returned value
00456      */
00457     int checkDim();
00458 
00459     /**
00460      * compute kernel matrix.  The data will be centered.
00461      */
00462     bool computeKernelMatrix(const dmatrix& src,dmatrix& kmat);
00463 
00464     /**
00465      * compute test kernel matrix.  The data will be centered.
00466      * It will be assumed that the source data (srcData) contains the
00467      * right data
00468      */
00469     bool computeTestKernelMatrix(const dmatrix& src,dmatrix& kmat) const;
00470 
00471     /**
00472      * compute test kernel vector.  The data will be centered.
00473      * It will be assumed that the source data (srcData) contains the
00474      * right data
00475      */
00476     bool computeTestKernelVector(const dvector& src,dvector& kvct) const;
00477 
00478   private:
00479 
00480     /**
00481      * Kernel PCA requires the original data set
00482      */
00483     dmatrix srcData;
00484 
00485     /**
00486      * Mean of rows of srcData
00487      */
00488     dvector Kunit;
00489 
00490     /**
00491      * Mean of columns of srcData
00492      */
00493     dvector unitK;
00494 
00495     /**
00496      * Mean of all values in the srcData
00497      */
00498     double unitKunit;
00499 
00500     /**
00501      * ordered set of eigenvectors (sorted with decreasing order of
00502      * eigenvalues).
00503      */
00504     dmatrix orderedEigVec;
00505 
00506     /**
00507      * the transformation matrix will contain just a subset of
00508      * the orderedEigVec matrix.
00509      */
00510     dmatrix transformMatrix;
00511 
00512     /**
00513      * ordered eigenvalues (in decreasing order)
00514      */
00515     dvector eigValues;
00516 
00517     /**
00518      * scaling factors for the whitening transformation
00519      */
00520     dvector whiteScale;
00521 
00522     /**
00523      * dimensionality being used.
00524      */
00525     int usedDimensionality;
00526   };
00527 
00528   bool read(ioHandler& handler,
00529             kernelPCA& kpca,
00530             const bool complete=true);
00531 
00532 
00533   bool write(ioHandler& handler,
00534              const kernelPCA& kpca,
00535              const bool complete=true);
00536 
00537 }
00538 
00539 #endif

Generated on Sat Apr 10 15:25:43 2010 for LTI-Lib by Doxygen 1.6.1