latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 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 .......: ltiHmmClassifier.h 00027 * authors ....: Benjamin Winkler 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 12.04.2002 00030 * revisions ..: $Id: ltiHmmClassifier.h,v 1.9 2006/02/07 18:18:00 ltilib Exp $ 00031 */ 00032 00033 00034 #ifndef _LTI_HMM_CLASSIFIER_H_ 00035 #define _LTI_HMM_CLASSIFIER_H_ 00036 00037 #include "ltiSupervisedSequenceClassifier.h" 00038 #include "ltiHmmTrainer.h" 00039 00040 namespace lti { 00041 00042 /** 00043 * This class defines training and classification methods for Hidden Markov Models (HMM) 00044 * using observation sequences. The algorithms are taken from "Fundamentals of speech 00045 * recognition" (L. Rabiner and B.-H. Juang, Prentice Hall, 1993) and can also be found in 00046 * "Erkennung kontinuierlicher Gebärdensprache mit Ganzwortmodellen" (H. C. Hienz, PhD thesis, 00047 * Chair of Technical Computer Science, 2000). The notation in this documentation is taken 00048 * from the latter literature. 00049 * 00050 * In case of classification, the probability \f$P(\mathbf{O}|\lambda)\f$ of the 00051 * observation sequence \f$\mathbf{O}\f$ is approximated by the observation probability 00052 * \f$P^*(\mathbf{O}|\lambda)\f$ of the best path \f$\mathbf{q^*}\f$. The best path is found 00053 * with the Viterbi algorithm. Increased computational efficiency and precision are achieved 00054 * by using scores with \f$Score(\mathbf{X}|\lambda):=-\ln P^*(\mathbf{X}|\lambda)\f$ 00055 * instead of probabilities. Note that the lowest score corresponds to the highest 00056 * probability and thus represents the best recognition result. 00057 * 00058 * <b>Note</b>: The values in the outputVector are not probabilities! 00059 * To match the value criteria (higher values represent better recognition results, positive values only), 00060 * scores are mapped to values between 0.0 and 1.0. Currently exponential, linear, and none are available. 00061 * <dl> 00062 * <dt>exponential (default)</dt> 00063 * <dd>\f$\left[ \frac{1.0}{score-lowestScore + 1.0} - 00064 * \frac{1.0}{(highestScore-lowestScore)+1.0}\right] \cdot 00065 * \frac{(highestScore-lowestScore)+1.0}{highestScore-lowestScore}\f$</dd> 00066 * <dt>linear</dt> 00067 * <dd>\f$value = \frac{highestScore-score}{highestScore-lowestScore}\f$</dd> 00068 * <dt>none</dt> 00069 * <dd>\f$value = score\f$</dd> 00070 * </dl> 00071 * 00072 */ 00073 class hmmClassifier : public supervisedSequenceClassifier { 00074 00075 public: 00076 00077 // -------------------------------------------------- 00078 // hmmClassifier::parameters 00079 // -------------------------------------------------- 00080 00081 /** 00082 * the parameters for the class hmmClassifier 00083 */ 00084 class parameters : public classifier::parameters { 00085 public: 00086 00087 00088 /** 00089 * default constructor 00090 */ 00091 parameters(); 00092 00093 /** 00094 * copy constructor 00095 * @param other the parameters %object to be copied 00096 */ 00097 parameters(const parameters& other); 00098 00099 /** 00100 * destructor 00101 */ 00102 virtual ~parameters(); 00103 00104 /** 00105 * returns name of this type 00106 */ 00107 const char* getTypeName() const; 00108 00109 /** 00110 * copy the contents of a parameters %object 00111 * @param other the parameters %object to be copied 00112 * @return a reference to this parameters %object 00113 */ 00114 parameters& copy(const parameters& other); 00115 00116 /** 00117 * copy the contents of a parameters object 00118 * @param other the parameters object to be copied 00119 * @return a reference to this parameters object 00120 */ 00121 parameters& operator=(const parameters& other); 00122 00123 00124 /** 00125 * returns a pointer to a clone of the parameters 00126 */ 00127 virtual classifier::parameters* clone() const; 00128 00129 /** 00130 * write the parameters in the given ioHandler 00131 * @param handler the ioHandler to be used 00132 * @param complete if true (the default) the enclosing begin/end will 00133 * be also written, otherwise only the data block will be written. 00134 * @return true if write was successful 00135 */ 00136 virtual bool write(ioHandler& handler,const bool complete=true) const; 00137 00138 /** 00139 * read the parameters from the given ioHandler 00140 * @param handler the ioHandler to be used 00141 * @param complete if true (the default) the enclosing begin/end will 00142 * be also written, otherwise only the data block will be written. 00143 * @return true if write was successful 00144 */ 00145 virtual bool read(ioHandler& handler,const bool complete=true); 00146 00147 # ifdef _LTI_MSC_6 00148 /** 00149 * this function is required by MSVC only, as a workaround for a 00150 * very awful bug, which exists since MSVC V.4.0, and still by 00151 * V.6.0 with all bugfixes (so called "service packs") remains 00152 * there... This method is also public due to another bug, so please 00153 * NEVER EVER call this method directly: use read() instead 00154 */ 00155 bool readMS(ioHandler& handler,const bool complete=true); 00156 00157 /** 00158 * this function is required by MSVC only, as a workaround for a 00159 * very awful bug, which exists since MSVC V.4.0, and still by 00160 * V.6.0 with all bugfixes (so called "service packs") remains 00161 * there... This method is also public due to another bug, so please 00162 * NEVER EVER call this method directly: use write() instead 00163 */ 00164 bool writeMS(ioHandler& handler,const bool complete=true) const; 00165 # endif 00166 00167 00168 /** 00169 * Parameters used for the training process. 00170 * Changing these parameters only affects the following training processes. 00171 */ 00172 hmmTrainer::parameters hmmTrainingParameters; 00173 00174 /** 00175 * Default hidden markov model used for the training process. 00176 * This can be useful for modifying attributes such as emissionScoreWeight. 00177 * Changing these parameters only affects the following training processes, 00178 * existing models are left untouched. 00179 */ 00180 hiddenMarkovModel defaultModel; 00181 00182 00183 /** 00184 * Mapping type used for scores. Currently exponential, linear and none are available. 00185 * <dl> 00186 * <dt>exponential</dt> 00187 * <dd>\f$value = \frac{1.0}{score - lowestScore + 1.0}\f$</dd> 00188 * <dt>linear</dt> 00189 * <dd>\f$value = \frac{highestscore-score}{highestScore-lowestScore}\f$</dd> 00190 * <dt>none</dt> 00191 * <dd>\f$value = score\f$</dd> 00192 * </dl> 00193 */ 00194 enum mappingType { 00195 exponential, /*!< choose exponential mapping*/ 00196 linear, /*!< choose linear mapping*/ 00197 none /*!< choose no mapping */ 00198 }; 00199 00200 /** 00201 * Specifies the mapping function to be used. 00202 * default: exponentialMapping 00203 */ 00204 mappingType mappingFunction; 00205 00206 }; 00207 00208 00209 /** 00210 * default constructor 00211 */ 00212 hmmClassifier(); 00213 00214 /** 00215 * copy constructor 00216 * @param other the object to be copied 00217 */ 00218 hmmClassifier(const hmmClassifier& other); 00219 00220 /** 00221 * destructor 00222 */ 00223 virtual ~hmmClassifier(); 00224 00225 /** 00226 * returns the name of this type ("hmmClassifier") 00227 */ 00228 virtual const char* getTypeName() const; 00229 00230 /** 00231 * copy data of "other" functor. 00232 * @param other the functor to be copied 00233 * @return a reference to this functor object 00234 */ 00235 hmmClassifier& copy(const hmmClassifier& other); 00236 00237 /** 00238 * alias for copy member 00239 * @param other the classifier to be copied 00240 * @return a reference to this classifier object 00241 */ 00242 hmmClassifier& operator=(const hmmClassifier& other); 00243 00244 /** 00245 * returns a pointer to a clone of this functor. 00246 */ 00247 virtual classifier* clone() const; 00248 00249 /** 00250 * returns used parameters 00251 */ 00252 const parameters& getParameters() const; 00253 00254 /** 00255 * write method 00256 */ 00257 virtual bool write(ioHandler &handler, const bool complete=true) const; 00258 00259 /** 00260 * read method 00261 */ 00262 virtual bool read(ioHandler &handler, const bool complete=true); 00263 00264 00265 // 00266 // training and classification methods: 00267 // 00268 00269 00270 /** @name Training routines 00271 * These methods are needed to train Hidden Markov models. 00272 */ 00273 //@{ 00274 00275 /** 00276 * Supervised sequence training. 00277 * The sequences in the <code>input</code> %vector are used for training 00278 * the %sequence %classifier. Each %sequence is associated with an id 00279 * given in the %vector <code>ids</code>. 00280 * Hidden Markov models are created for all given ids, existing models being deleted first. 00281 * After the training process, the outputTemplate is generated on the training set. 00282 * @param input %vector of training %sequences 00283 * @param ids the classes of the training sequences 00284 * @return true if successful, false otherwise. (if false you can check 00285 * the error message with getStatusString()) 00286 */ 00287 virtual bool train(const std::vector< sequence<dvector> > &input, 00288 const ivector& ids); 00289 00290 /** 00291 * Training of a single model. 00292 * The given %sequences are used to train the model of the given id. 00293 * If such a model already exists internally, it will be overwritten. 00294 * Training is performed with the training %parameters given in the parameters class. 00295 * 00296 * Note: if you train a single model this way, the output template may contain incorrect values! 00297 */ 00298 bool train(std::vector< sequence<dvector> > &input, int id); 00299 00300 /** 00301 * Deletes all models saved internally. 00302 */ 00303 void reset(); 00304 00305 //@} 00306 00307 00308 /** @name Classification routines. 00309 * These methods are used for classification. 00310 */ 00311 //@{ 00312 00313 00314 /** 00315 * Classification. 00316 * Classifies the %sequence of features and returns the outputVector with 00317 * the classification result. 00318 * @param observations the %sequence to be classified 00319 * @param result the result of the classification 00320 * @return false if an error occurred during classification else true 00321 */ 00322 virtual bool classify(const sequence<dvector>& observations, 00323 outputVector& result); 00324 00325 //@} 00326 00327 //@{ 00328 00329 00330 /** 00331 * Reduced Classification. 00332 * Classifies the %sequence of features only with a reduced number 00333 * of models given in usedModelsIDNameMap. 00334 * Returns the outputVector with the classification result. 00335 * @param observations the %sequence to be classified 00336 * @param result the result of the classification 00337 * @param usedModelsIDNameMap map of hmm models given by id and name 00338 * @return false if an error occurred during classification else true 00339 */ 00340 bool reducedClassify(const sequence<dvector>& observations, 00341 outputVector& result, 00342 std::map<int, std::string> usedModelsIDNameMap); 00343 00344 00345 //@} 00346 00347 /** @name Direct access routines 00348 * These methods are used to directly access/change the Hidden Markov models used internally. 00349 * Note that changing single models may lead to incorrect output templates! 00350 */ 00351 //@{ 00352 00353 /** 00354 * Query id's of trained models. 00355 * @return vector containing the ids of all models of this classifier. 00356 */ 00357 ivector getIDs(); 00358 00359 /** 00360 * Returns a copy of the model with the given id. 00361 * If no such model exists, the empty default model given in parameters is returned. 00362 */ 00363 hiddenMarkovModel getHMM(int id) const; 00364 00365 /** 00366 * Set the model to be used for the given id. 00367 * 00368 * Note: the output template may contain incorrect values hereafter! 00369 * 00370 * @return true, if successful, false otherwise 00371 */ 00372 bool setHMM(hiddenMarkovModel &model, int id); 00373 00374 /** 00375 * Delete the model with the given id. 00376 * 00377 * Note: the output template may contain incorrect values after this! 00378 * 00379 * @return true, if successful, false otherwise. 00380 */ 00381 bool deleteHMM(int id); 00382 00383 /** 00384 * Set the name of a specific model (if a model with the given ID exists). 00385 */ 00386 void setName(int id, const std::string &theName); 00387 00388 /** 00389 * Generate a map ID -> name for all loaded models. 00390 */ 00391 void generateIndexNameMap(std::map<int, std::string> &theMap) const; 00392 00393 /** Returns the length of the shortest model. This allows to tell if 00394 * an observation of a certain length can be classified by this classifier. 00395 * If no models are available, -1 will be returned. */ 00396 int getShortestModelLength() const; 00397 00398 //@} 00399 00400 00401 protected: 00402 00403 /** 00404 * the models with the given ids. 00405 */ 00406 std::map<int, hiddenMarkovModel> theModels; 00407 00408 /** 00409 * feature dimension (saved here for faster access) 00410 */ 00411 int featureDimension; 00412 00413 }; 00414 } 00415 00416 #endif