1 /** 2 * @file methods/hmm/hmm_model.hpp 3 * @author Ryan Curtin 4 * 5 * A serializable HMM model that also stores the type. 6 * 7 * mlpack is free software; you may redistribute it and/or modify it under the 8 * terms of the 3-clause BSD license. You should have received a copy of the 9 * 3-clause BSD license along with mlpack. If not, see 10 * http://www.opensource.org/licenses/BSD-3-Clause for more information. 11 */ 12 #ifndef MLPACK_METHODS_HMM_HMM_MODEL_HPP 13 #define MLPACK_METHODS_HMM_HMM_MODEL_HPP 14 15 #include "hmm.hpp" 16 #include <mlpack/methods/gmm/gmm.hpp> 17 #include <mlpack/methods/gmm/diagonal_gmm.hpp> 18 19 namespace mlpack { 20 namespace hmm { 21 22 enum HMMType : char 23 { 24 DiscreteHMM = 0, 25 GaussianHMM, 26 GaussianMixtureModelHMM, 27 DiagonalGaussianMixtureModelHMM 28 }; 29 30 /** 31 * A serializable HMM model that also stores the type. 32 */ 33 class HMMModel 34 { 35 private: 36 //! The type of the HMM. 37 HMMType type; 38 //! Not used if type is not DiscreteHMM. 39 HMM<distribution::DiscreteDistribution>* discreteHMM; 40 //! Not used if type is not GaussianHMM. 41 HMM<distribution::GaussianDistribution>* gaussianHMM; 42 //! Not used if type is not GaussianMixtureModelHMM. 43 HMM<gmm::GMM>* gmmHMM; 44 //! Not used if type is not DiagonalGaussianMixtureModelHMM. 45 HMM<gmm::DiagonalGMM>* diagGMMHMM; 46 47 public: 48 //! Construct a model of the given type. HMMModel(const HMMType type=HMMType::DiscreteHMM)49 HMMModel(const HMMType type = HMMType::DiscreteHMM) : 50 type(type), 51 discreteHMM(NULL), 52 gaussianHMM(NULL), 53 gmmHMM(NULL), 54 diagGMMHMM(NULL) 55 { 56 if (type == HMMType::DiscreteHMM) 57 discreteHMM = new HMM<distribution::DiscreteDistribution>(); 58 else if (type == HMMType::GaussianHMM) 59 gaussianHMM = new HMM<distribution::GaussianDistribution>(); 60 else if (type == HMMType::GaussianMixtureModelHMM) 61 gmmHMM = new HMM<gmm::GMM>(); 62 else if (type == HMMType::DiagonalGaussianMixtureModelHMM) 63 diagGMMHMM = new HMM<gmm::DiagonalGMM>(); 64 } 65 66 //! Copy another model. HMMModel(const HMMModel & other)67 HMMModel(const HMMModel& other) : 68 type(other.type), 69 discreteHMM(NULL), 70 gaussianHMM(NULL), 71 gmmHMM(NULL), 72 diagGMMHMM(NULL) 73 { 74 if (type == HMMType::DiscreteHMM) 75 discreteHMM = 76 new HMM<distribution::DiscreteDistribution>(*other.discreteHMM); 77 else if (type == HMMType::GaussianHMM) 78 gaussianHMM = 79 new HMM<distribution::GaussianDistribution>(*other.gaussianHMM); 80 else if (type == HMMType::GaussianMixtureModelHMM) 81 gmmHMM = new HMM<gmm::GMM>(*other.gmmHMM); 82 else if (type == HMMType::DiagonalGaussianMixtureModelHMM) 83 diagGMMHMM = new HMM<gmm::DiagonalGMM>(*other.diagGMMHMM); 84 } 85 86 //! Take ownership of another model. HMMModel(HMMModel && other)87 HMMModel(HMMModel&& other) : 88 type(other.type), 89 discreteHMM(other.discreteHMM), 90 gaussianHMM(other.gaussianHMM), 91 gmmHMM(other.gmmHMM), 92 diagGMMHMM(other.diagGMMHMM) 93 { 94 other.type = HMMType::DiscreteHMM; 95 other.discreteHMM = new HMM<distribution::DiscreteDistribution>(); 96 other.gaussianHMM = NULL; 97 other.gmmHMM = NULL; 98 other.diagGMMHMM = NULL; 99 } 100 101 //! Copy assignment operator. operator =(const HMMModel & other)102 HMMModel& operator=(const HMMModel& other) 103 { 104 if (this == &other) 105 return *this; 106 107 delete discreteHMM; 108 delete gaussianHMM; 109 delete gmmHMM; 110 delete diagGMMHMM; 111 112 discreteHMM = NULL; 113 gaussianHMM = NULL; 114 gmmHMM = NULL; 115 diagGMMHMM = NULL; 116 117 type = other.type; 118 if (type == HMMType::DiscreteHMM) 119 discreteHMM = 120 new HMM<distribution::DiscreteDistribution>(*other.discreteHMM); 121 else if (type == HMMType::GaussianHMM) 122 gaussianHMM = 123 new HMM<distribution::GaussianDistribution>(*other.gaussianHMM); 124 else if (type == HMMType::GaussianMixtureModelHMM) 125 gmmHMM = new HMM<gmm::GMM>(*other.gmmHMM); 126 else if (type == HMMType::DiagonalGaussianMixtureModelHMM) 127 diagGMMHMM = new HMM<gmm::DiagonalGMM>(*other.diagGMMHMM); 128 129 return *this; 130 } 131 132 //! Clean memory. ~HMMModel()133 ~HMMModel() 134 { 135 delete discreteHMM; 136 delete gaussianHMM; 137 delete gmmHMM; 138 delete diagGMMHMM; 139 } 140 141 /** 142 * Given a functor type, perform that functor with the optional extra info on 143 * the HMM. 144 */ 145 template<typename ActionType, 146 typename ExtraInfoType> PerformAction(ExtraInfoType * x)147 void PerformAction(ExtraInfoType* x) 148 { 149 if (type == HMMType::DiscreteHMM) 150 ActionType::Apply(*discreteHMM, x); 151 else if (type == HMMType::GaussianHMM) 152 ActionType::Apply(*gaussianHMM, x); 153 else if (type == HMMType::GaussianMixtureModelHMM) 154 ActionType::Apply(*gmmHMM, x); 155 else if (type == HMMType::DiagonalGaussianMixtureModelHMM) 156 ActionType::Apply(*diagGMMHMM, x); 157 } 158 159 //! Serialize the model. 160 template<typename Archive> serialize(Archive & ar,const unsigned int version)161 void serialize(Archive& ar, const unsigned int version) 162 { 163 ar & BOOST_SERIALIZATION_NVP(type); 164 165 // If necessary, clean memory. 166 if (Archive::is_loading::value) 167 { 168 delete discreteHMM; 169 delete gaussianHMM; 170 delete gmmHMM; 171 delete diagGMMHMM; 172 173 discreteHMM = NULL; 174 gaussianHMM = NULL; 175 gmmHMM = NULL; 176 diagGMMHMM = NULL; 177 } 178 179 if (type == HMMType::DiscreteHMM) 180 ar & BOOST_SERIALIZATION_NVP(discreteHMM); 181 else if (type == HMMType::GaussianHMM) 182 ar & BOOST_SERIALIZATION_NVP(gaussianHMM); 183 else if (type == HMMType::GaussianMixtureModelHMM) 184 ar & BOOST_SERIALIZATION_NVP(gmmHMM); 185 186 // Backward compatibility: new versions of HMM has a Diagonal GMM type. 187 if (version > 0) 188 { 189 if (type == HMMType::DiagonalGaussianMixtureModelHMM) 190 ar & BOOST_SERIALIZATION_NVP(diagGMMHMM); 191 } 192 } 193 194 // Accessor method for type of HMM Type()195 HMMType Type() { return type; } 196 197 /** 198 * Accessor methods for discreteHMM, gaussianHMM, gmmHMM, and diagGMMHMM. 199 * Note that an instatiation of this class will only contain one type of HMM 200 * (as indicated by the "type" instance variable) - the other two pointers 201 * will be NULL. 202 * 203 * For instance, if the HMMModel object holds a discrete HMM, then: 204 * type --> DiscreteHMM 205 * gaussianHMM --> NULL 206 * gmmHMM --> NULL 207 * diagGMMHMM --> NULL 208 * discreteHMM --> HMM<DiscreteDistribution> object 209 * and hence, calls to GMMHMM(), DiagGMMHMM() and GaussianHMM() will return 210 * NULL. Only the call to DiscreteHMM() will return a non NULL pointer. 211 * 212 * Hence, in practice, a user should be careful to first check the type of HMM 213 * (by calling the Type() accessor) and then perform subsequent actions, to 214 * avoid null pointer dereferences. 215 */ DiscreteHMM()216 HMM<distribution::DiscreteDistribution>* DiscreteHMM() { return discreteHMM; } GaussianHMM()217 HMM<distribution::GaussianDistribution>* GaussianHMM() { return gaussianHMM; } GMMHMM()218 HMM<gmm::GMM>* GMMHMM() { return gmmHMM; } DiagGMMHMM()219 HMM<gmm::DiagonalGMM>* DiagGMMHMM() { return diagGMMHMM; } 220 }; 221 222 } // namespace hmm 223 } // namespace mlpack 224 225 //! Set the serialization version of the HMMModel class. 226 BOOST_CLASS_VERSION(mlpack::hmm::HMMModel, 1); 227 228 #endif 229