CVR-Lib last update 20 Sep 2009

cvrPCA.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C)  2000, 2001, 2002, 2003, 2004, 2005, 2006
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  * Copyright (C) 2008
00005  * Pablo Alvarado
00006  *
00007  * This file is part of the Computer Vision and Robotics Library (CVR-Lib )
00008  *
00009  * The CVR-Lib is free software; you can redistribute it and/or
00010  * modify it under the terms of the BSD License.
00011  *
00012  * All rights reserved.
00013  *
00014  * Redistribution and use in source and binary forms, with or without
00015  * modification, are permitted provided that the following conditions are met:
00016  *
00017  * 1. Redistributions of source code must retain the above copyright notice,
00018  *    this list of conditions and the following disclaimer.
00019  *
00020  * 2. Redistributions in binary form must reproduce the above copyright notice,
00021  *    this list of conditions and the following disclaimer in the documentation
00022  *    and/or other materials provided with the distribution.
00023  *
00024  * 3. Neither the name of the authors nor the names of its contributors may be
00025  *    used to endorse or promote products derived from this software without
00026  *    specific prior written permission.
00027  *
00028  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00029  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00030  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00031  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00032  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00033  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00034  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00035  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00036  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00037  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00038  * POSSIBILITY OF SUCH DAMAGE.
00039  */
00040 
00041 /**
00042  * \file   cvrPCA.h
00043  *         Principal Components Analysis
00044  * \author Jochen Wickel
00045  * \author Pablo Alvarado
00046  * \date   27.11.2000
00047  *
00048  * revisions ..: $Id: cvrPCA.h,v 1.1 2008/05/08 15:00:29 alvarado Exp $
00049  */
00050 
00051 #ifndef _CVR_P_C_A_H_
00052 #define _CVR_P_C_A_H_
00053 
00054 #include "cvrLinearAlgebraFunctor.h"
00055 #include "cvrMatrix.h"
00056 
00057 namespace cvr {
00058   /**
00059    * Principal Components Analysis (PCA).
00060    *
00061    * Functor for computing the principal components of a data set.
00062    *
00063    * It receives a set of input vectors in form of a matrix (each row of
00064    * the matrix corresponds to an input vector), which will be transformed
00065    * with PCA.
00066    *
00067    * The first time you use the apply()-method, the transformation
00068    * matrix will be computed.  You can use this transformation matrix
00069    * with other data sets using the transform() methods.
00070    *
00071    * Please note that the eigenvector matrices will contain the
00072    * eigenvector in the COLUMNS and not in the rows, as could be
00073    * expected.  This avoids the requirement of transposing matrices in
00074    * the vector transformations.
00075    *
00076    * For large data matrices is is advisable to use singular value
00077    * decomposition instead of an eigensystem for the PCA. The
00078    * operation will usually be faster and using less memory. To do so
00079    * set parameters::useSVD to true.
00080    *
00081    * @ingroup gLinearAlgebra
00082    */
00083   template <typename T>
00084   class pca : public linearAlgebraFunctor {
00085   public:
00086     /**
00087      * The parameters for the class pca
00088      */
00089     class parameters : public linearAlgebraFunctor::parameters {
00090     public:
00091       /**
00092        * Default constructor
00093        */
00094       parameters();
00095 
00096       /**
00097        * Copy constructor
00098        * @param other the parameters object to be copied
00099        */
00100       parameters(const parameters& other);
00101 
00102       /**
00103        * Destructor
00104        */
00105       ~parameters();
00106 
00107       /**
00108        * Return  name of this class
00109        */
00110       const std::string& name() const;
00111 
00112       /**
00113        * Copy the contents of a parameters object
00114        * @param other the parameters object to be copied
00115        * @return a reference to this parameters object
00116        */
00117       parameters& copy(const parameters& other);
00118 
00119       /**
00120        * Assigns the contents of the other object to this object
00121        */
00122       parameters& operator=(const parameters& other);
00123 
00124       /**
00125        * Return a pointer to a clone of the parameters
00126        */
00127       virtual parameters* clone() const;
00128 
00129       /**
00130        * Return a pointer to a new instance of the parameters
00131        */
00132       virtual parameters* newInstance() const;
00133 
00134       /**
00135        * Read the parameters from the given ioHandler
00136        *
00137        * @param handler the ioHandler to be used
00138        * @param complete if true (the default) the enclosing begin/end will
00139        *        be also read, otherwise only the data block will be read.
00140        * @return true if write was successful
00141        */
00142       virtual bool read(ioHandler &handler, const bool complete=true);
00143 
00144       /**
00145        * Write the parameters in the given ioHandler.
00146        *
00147        * @param handler the ioHandler to be used
00148        * @param complete if true (the default) the enclosing begin/end will
00149        *        be also written, otherwise only the data block will be
00150        *        written.
00151        * @return true if write was successful
00152        */
00153       virtual bool write(ioHandler& handler,const bool complete=true) const;
00154 
00155       // --------------
00156       // The parameters
00157       // --------------
00158 
00159       /**
00160        * Final dimension of the reduced vectors.
00161        *
00162        * Default value: 3
00163        */
00164       int resultDimension;
00165 
00166       /**
00167        * This flag determines, if the functor should determine a
00168        * maximum allowable dimension itself. "Maximum dimension" means
00169        * that the dimension is equal to the number of eigenvalues of
00170        * the covariance matrix which are larger than zero.
00171        *
00172        * Default value: \c false
00173        */
00174       bool autoDimension;
00175 
00176       /**
00177        * This flag determines if the functor should use the
00178        * correlation coefficient matrix (flag is true) for eigenvector
00179        * computation or the covariance matrix (flag is false).
00180        *
00181        * Default value: \c false.
00182        */
00183       bool useCorrelation;
00184 
00185       /**
00186        * This flag determines if the functor should perform a
00187        * whitening transform of the data. Whitening means that
00188        * 1. A PCA is performed, using the covariance matrix for
00189        *    eigenvector computation
00190        * 2. A scaling of the transformed data by the inverse of the
00191        *    square root of the eigenvalues.
00192        *
00193        * You have to set useCorrelation to false if you use whitening.
00194        *
00195        * Default value: \c false.
00196        */
00197       bool whitening;
00198 
00199       /**
00200        * The factor which determines relevant eigenvectors. An eigenvector
00201        * is considered relevant if its eigenvalue is at least as large
00202        * as the largest eigenvalue divided by this number. Usually,
00203        * it takes values between 1e4 and 1e6.
00204        *
00205        * Default value: T(100000)
00206        */
00207       T relevance;
00208 
00209       /**
00210        * This flag denotes if the transformed data should be
00211        * centered around zero. This is the usual behaviour of
00212        * the PCA, but for some special operations it may be
00213        * necessary to disable this. If the flag is false,
00214        * the mean of the transformed data is moved to the transformed
00215        * mean of the source data.
00216        *
00217        * Default value: true
00218        */
00219       bool centerData;
00220 
00221       /**
00222        * When \c true, singular value decomposition instead of eigensystem
00223        * solution is used to calculate the eigenvectors and
00224        * eigenvalues. This can be much faster and less memory consuming.
00225        *
00226        * Default value: \c false.
00227        */
00228       bool useSVD;
00229     };
00230 
00231   protected:
00232 
00233     /**
00234      * Default constructor.
00235      *
00236      * @param createDefaultParams if true (default) a default parameters
00237      *                            object will be created.
00238      */
00239     pca(const bool createDefaultParams);
00240 
00241   public:
00242     /**
00243      * Default constructor.
00244      */
00245     pca();
00246 
00247     /**
00248      * Default constructor with parameters
00249      *
00250      */
00251     pca(const parameters& par);
00252 
00253     /**
00254      * Copy constructor.
00255      *
00256      * @param other the object to be copied
00257      */
00258     pca(const pca& other);
00259 
00260     /**
00261      * Destructor
00262      */
00263     virtual ~pca();
00264 
00265     /**
00266      * Returns the name of this type ("pca")
00267      */
00268     virtual const std::string& name() const;
00269 
00270     /**
00271      * Computes the principal components of the data matrix
00272      * and transforms it according to the new coordinate system.
00273      * The result is the transformed matrix.
00274      * Data and result must not be references to the same matrix.
00275      * Data points are expected to be in the rows of the data matrix.
00276      *
00277      * If you don't need to transform the input data, and just want to
00278      * use the input matrix to compute the principal components you
00279      * can use the method computeTransformMatrix().  If you just need
00280      * to transform the data, without computing the transformation matrix, you
00281      * can use the method transform().
00282      *
00283      * @param data matrix<T> with the source data.
00284      * @param result matrix<T> with the result data.
00285      * @return true if the PCA could be computed, false otherwise
00286      */
00287     virtual bool apply(const matrix<T>& data, matrix<T>& result);
00288 
00289     /**
00290      * On-Place version of the transformation.
00291      *
00292      * If you don't need to transform the input data, and just want to
00293      * use the input matrix to compute the principal components you
00294      * can use the method computeTransformMatrix().  If you just need
00295      * to transform the data, without computing the transformation matrix, you
00296      * can use the method transform().
00297      *
00298      * @param srcdest matrix<T> with the source data, which will also contain
00299      *        the result.
00300      * @return a reference to <code>srcdest</code>.
00301      */
00302     virtual bool apply(matrix<T>& srcdest);
00303 
00304     /**
00305      * Transforms a single vector according to a previously computed
00306      * transformation matrix. (this is an alias for the transform() method)
00307      */
00308     virtual inline bool apply(const vector<T> &src, vector<T>& result) {
00309       return transform(src,result);
00310     }
00311 
00312     /**
00313      * Pass the covariance matrix and the mean values directly
00314      * to the functor to generate the transform matrix.
00315      *
00316      * If you know the mean and covariance of your data, you can use this
00317      * method to speed up the computations of the transformation matrix.
00318      * Otherwise, just call one of the apply() methods with your data vectors
00319      * in the rows of the matrix.  The covariance and mean vectors will be
00320      * computed there automatically.
00321      */
00322     bool setCovarianceAndMean(const matrix<T>& coVar,
00323                               const vector<T>& meanVec);
00324 
00325     /**
00326      * Transforms a single vector according to a previously computed
00327      * transformation matrix.
00328      *
00329      * @param src the data vector
00330      * @param result the vector which will receive the transformed data
00331      * @return a reference to <code>result</code>
00332      */
00333     virtual bool transform(const vector<T> &src, vector<T>& result) const;
00334 
00335     /**
00336      * Transform an entire matrix according to a previously computed
00337      * transformation matrix. Unfortunately, we must choose a name
00338      * different from apply.
00339      *
00340      * @param src the data matrix
00341      * @param result the matrix which will receive the transformed data
00342      * @return true if successful, false otherwise.
00343      */
00344     virtual bool transform(const matrix<T> &src, matrix<T>& result) const;
00345 
00346     /**
00347      * Transform an entire matrix according to a previously computed
00348      * transformation matrix. Unfortunately, we must choose a name
00349      * different from apply.
00350      * @param srcdest the data matrix.  The result will be left here too.
00351      * @return true if successful, false otherwise.
00352      */
00353     virtual bool transform(matrix<T> &srcdest) const;
00354 
00355     /**
00356      * Compute the transformation matrix.  Similar to the apply() method,
00357      * but it does not transform the given data (this saves some time).
00358      *
00359      * @param src the matrix with the input data to be analysed.
00360      * @return true if transformation matrix could be computed, false otherwise
00361      */
00362     virtual bool computeTransformMatrix(const matrix<T>& src);
00363 
00364     /**
00365      * Alias for computeTransformMatrix()
00366      */
00367     virtual bool train(const matrix<T>& src);
00368 
00369     /**
00370      * Reconstructs a data vector \c dest from the given coefficients
00371      * \c coeff, using the transformMatrix found by
00372      * computeTransformMatrix() or apply() and the appropriate offset.
00373      *
00374      * @param coeff PCA coefficients for reconstruction.
00375      * @param dest reconstructed data vector.
00376      * @return true if reconstruction was successful
00377      */
00378     virtual bool reconstruct(const vector<T>& coeff, vector<T>& dest) const;
00379 
00380     /**
00381      * Reconstructs a set of data vectors \c dest from the given
00382      * coefficients \c coeff, using the transformMatrix found by
00383      * computeTransformMatrix() or apply() and the appropriate
00384      * offset. As usual \c coeff as well as \c dest contain one data
00385      * vector per row.
00386      *
00387      * @param coeff each row contains PCA coefficients for reconstruction.
00388      * @param dest each row is one reconstructed data vector.
00389      * @return true if reconstruction was successful
00390      */
00391     virtual bool reconstruct(const matrix<T>& coeff, matrix<T>& dest) const;
00392 
00393     /**
00394      * Returns the previously computed transform matrix.
00395      *
00396      * @param result the matrix which will receive the transformation
00397      *        matrix.
00398      * @return true if the matrix could be computed, false otherwise.
00399      */
00400     virtual bool getTransformMatrix(matrix<T>& result) const;
00401 
00402     /**
00403      * Returns the previously computed transform matrix.
00404      *
00405      * @return a const reference to the last computed or used transformation
00406      *           matrix.
00407      */
00408     virtual const matrix<T>& getTransformMatrix() const;
00409 
00410     /**
00411      * Returns the previously computed offset vector, which corresponds to the
00412      * mean of the data.
00413      *
00414      * @param result the offset vector will be written here.
00415      * @return true if the matrix could be computed, false otherwise.
00416      */
00417     virtual bool getOffsetVector(vector<T>& result) const;
00418 
00419     /**
00420      * Returns the previously computed offset vector, which corresponds to the
00421      * mean of the data.
00422      *
00423      * @return a const reference to the last computed or used offset vector.
00424      */
00425     virtual const vector<T>& getOffsetVector() const;
00426 
00427     /**
00428      * Returns the previously computed eigenvalues of the covariance
00429      * matrix.
00430      *
00431      * @param result the vector which will receive the eigenvalues.
00432      * @return true if the values could be obtained, false otherwise.
00433      */
00434     virtual bool getEigenValues(vector<T>& result) const;
00435 
00436     /**
00437      * Returns the previously computed eigenvalues of the covariance
00438      * matrix.
00439      *
00440      * @return a const reference to the last computed eigenvalues
00441      */
00442     virtual const vector<T>& getEigenValues() const;
00443 
00444     /**
00445      * Returns the previously computed eigenvectors of the covariance
00446      * matrix.
00447      *
00448      * @param result the matrix which will receive the eigenvectors.
00449      *        Each column of the matrix contains one eigenvector.
00450      * @return true if the vectors could be obtained, false otherwise
00451      */
00452     virtual bool getEigenVectors(matrix<T>& result) const;
00453 
00454     /**
00455      * Returns the previously computed eigenvectors of the covariance
00456      * matrix.
00457      *
00458      * This method will call the normal getEigenVectors() methods and
00459      * after that will transpose the obtained matrix, i.e. it is faster
00460      * to get the eigenvectors in the columns.
00461      *
00462      * @param result the matrix which will receive the eigenvectors.
00463      *        Each row of the matrix contains one eigenvector.
00464      * @return true if the vectors could be obtained, false otherwise
00465      */
00466     virtual bool getEigenVectorsInRows(matrix<T>& result) const;
00467 
00468     /**
00469      * Returns the previously computed eigenvectors of the covariance
00470      * matrix.
00471      *
00472      * @return a const reference to the last computed eigenvectors
00473      */
00474     virtual const matrix<T>& getEigenVectors() const;
00475 
00476     /**
00477      * Set the dimension to which the vectors should be reduced.  This
00478      * is just considered when computing the transformation
00479      * matrix. After this matrix is determined the (destination)
00480      * dimension is fixed and just can be changed by recalculating the
00481      * transformation matrix.
00482      */
00483     virtual void setDimension(int k);
00484 
00485     /**
00486      * Copy data of "other" functor.
00487      *
00488      * @param other the functor to be copied
00489      * @return a reference to this functor object
00490      */
00491     pca& copy(const pca& other);
00492 
00493     /**
00494      * Alias for copy.
00495      */
00496     pca& operator=(const pca& other);
00497 
00498     /**
00499      * Return a pointer to a clone of this functor.
00500      */
00501     virtual functor* clone() const;
00502 
00503     /**
00504      * Return a pointer to a new instance of this functor.
00505      */
00506     virtual functor* newInstance() const;
00507 
00508     /**
00509      * Return used parameters
00510      */
00511     const parameters& getParameters() const;
00512 
00513     /**
00514      * Update functor's parameters.
00515      *
00516      * This member initializes some internal data according to the values in
00517      * the parameters.
00518      *
00519      * @return true if successful, false otherwise
00520      */
00521     virtual bool updateParameters();
00522 
00523     /**
00524      * Read this functor from the given handler.
00525      */
00526     virtual bool read(ioHandler &handler, const bool complete=true);
00527 
00528     /**
00529      * Write this functor to the given handler.
00530      */
00531     virtual bool write(ioHandler &handler, const bool complete=true) const;
00532 
00533     /**
00534      * Number of dimensions considered in the transformation
00535      * @return the number of dimensions used for the transformation.  It
00536      *         is always less or equal the number of dimensions of the input
00537      *         vectors.
00538      */
00539     int getUsedDimension() const {
00540       return usedDimensionality_;
00541     }
00542 
00543   protected:
00544     /**
00545      * Determines the intrinsic dimensionality of the data set if the
00546      * user specify autoDim, otherwise return parameters::resultDim.
00547      * The member usedDimensionality will be set with the returned value
00548      */
00549     int checkDim();
00550 
00551     /**
00552      * Resets all private members to size 0. Used when an error occurs
00553      * in the calculation of the transform matrix.
00554      */
00555     void reset();
00556 
00557   protected:
00558     /**
00559      * Ordered eigen vectors
00560      */
00561     matrix<T> orderedEigVec_;
00562 
00563     /**
00564      * Transformation matrix
00565      */
00566     matrix<T> transformMatrix_;
00567 
00568     /**
00569      * Eigenvalues
00570      */
00571     vector<T> eigValues_;
00572 
00573     /**
00574      * Offset
00575      */
00576     vector<T> offset_;
00577 
00578     /**
00579      * Transformed offset
00580      */
00581     vector<T> transformedOffset_;
00582 
00583     /**
00584      * Scale
00585      */
00586     vector<T> scale_;
00587 
00588     /**
00589      * Whitening scale
00590      */
00591     vector<T> whiteScale_;
00592 
00593     /**
00594      * Dimensionality being used.
00595      */
00596     int usedDimensionality_;
00597   };
00598 
00599 
00600 }
00601 
00602 #endif

Generated on Sun Sep 20 22:08:00 2009 for CVR-Lib by Doxygen 1.5.8