GestureRecognitionToolkit  Version: 0.1.0
The Gesture Recognition Toolkit (GRT) is a cross-platform, open-source, c++ machine learning library for real-time gesture recognition.
ParticleClassifier.cpp
1 /*
2  GRT MIT License
3  Copyright (c) <2012> <Nicholas Gillian, Media Lab, MIT>
4 
5  Permission is hereby granted, free of charge, to any person obtaining a copy of this software
6  and associated documentation files (the "Software"), to deal in the Software without restriction,
7  including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
9  subject to the following conditions:
10 
11  The above copyright notice and this permission notice shall be included in all copies or substantial
12  portions of the Software.
13 
14  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15  LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
18  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
21 #include "ParticleClassifier.h"
22 
23 GRT_BEGIN_NAMESPACE
24 
25 //Register the ParticleClassifier module with the Classifier base class
26 RegisterClassifierModule< ParticleClassifier > ParticleClassifier::registerModule("ParticleClassifier");
27 
28 ParticleClassifier::ParticleClassifier( const unsigned int numParticles,const Float sensorNoise,const Float transitionSigma,const Float phaseSigma,const Float velocitySigma )
29 {
30  this->numParticles = numParticles;
31  this->sensorNoise = sensorNoise;
32  this->transitionSigma = transitionSigma;
33  this->phaseSigma = phaseSigma;
34  this->velocitySigma = velocitySigma;
35  useNullRejection = true;
36  supportsNullRejection = true;
37  classType = "ParticleClassifier";
38  classifierType = classType;
39  classifierMode = TIMESERIES_CLASSIFIER_MODE;
40  debugLog.setProceedingText("[DEBUG ParticleClassifier]");
41  errorLog.setProceedingText("[ERROR ParticleClassifier]");
42  trainingLog.setProceedingText("[TRAINING ParticleClassifier]");
43  warningLog.setProceedingText("[WARNING ParticleClassifier]");
44 }
45 
47  *this = rhs;
48 }
49 
51 {
52 }
53 
55 
56  if( this != &rhs ){
57 
58  this->numParticles = rhs.numParticles;
59  this->sensorNoise = rhs.sensorNoise;
60  this->transitionSigma = rhs.transitionSigma;
61  this->phaseSigma = rhs.phaseSigma;
62  this->velocitySigma = rhs.velocitySigma;
63  this->particleFilter = rhs.particleFilter;
64 
65  //Copy the classifier variables
66  copyBaseVariables( (Classifier*)&rhs );
67  }
68  return *this;
69 }
70 
72  if( classifier == NULL ) return false;
73 
74  if( this->getClassifierType() == classifier->getClassifierType() ){
75  ParticleClassifier *ptr = (ParticleClassifier*)classifier;
76 
77  this->numParticles = ptr->numParticles;
78  this->sensorNoise = ptr->sensorNoise;
79  this->transitionSigma = ptr->transitionSigma;
80  this->phaseSigma = ptr->phaseSigma;
81  this->velocitySigma = ptr->velocitySigma;
82  this->particleFilter = ptr->particleFilter;
83 
84  //Copy the classifier variables
85  return copyBaseVariables( classifier );
86  }
87  return false;
88 }
89 
91 
92  clear();
93 
94  numClasses = trainingData.getNumClasses();
95  numInputDimensions = trainingData.getNumDimensions();
96  ranges = trainingData.getRanges();
97 
98  //Scale the training data if needed
99  if( useScaling ){
100  trainingData.scale(0, 1);
101  }
102 
103  //Train the particle filter
104  particleFilter.train( numParticles, trainingData, sensorNoise, transitionSigma, phaseSigma, velocitySigma );
105 
106  classLabels.resize(numClasses);
107  classLikelihoods.resize(numClasses,0);
108  classDistances.resize(numClasses,0);
109 
110  for(unsigned int i=0; i<numClasses; i++){
111  classLabels[i] = trainingData.getClassTracker()[i].classLabel;
112  }
113 
114  trained = true;
115 
116  return trained;
117 }
118 
120 
121  if( !trained ){
122  errorLog << "predict_(VectorDouble &inputVector) - The model has not been trained!" << std::endl;
123  return false;
124  }
125 
126  if( numInputDimensions != inputVector.size() ){
127  errorLog << "predict_(VectorDouble &inputVector) - The number of features in the model " << numInputDimensions << " does not match that of the input vector " << inputVector.size() << std::endl;
128  return false;
129  }
130 
131  //Scale the input data if needed
132  if( useScaling ){
133  for(unsigned int j=0; j<numInputDimensions; j++){
134  inputVector[j] = scale(inputVector[j],ranges[j].minValue,ranges[j].maxValue,0,1);
135  }
136  }
137 
138  predictedClassLabel = 0;
139  maxLikelihood = 0;
140  std::fill(classLikelihoods.begin(),classLikelihoods.end(),0);
141  std::fill(classDistances.begin(),classDistances.end(),0);
142 
143  //Update the particle filter
144  particleFilter.filter( inputVector );
145 
146  //Count the number of particles per class
147  unsigned int gestureTemplate = 0;
148  unsigned int gestureLabel = 0;
149  unsigned int gestureIndex = 0;
150  for(unsigned int i=0; i<numParticles; i++){
151  gestureTemplate = (unsigned int)particleFilter[i].x[0]; //The first element in the state vector is the gesture template index
152  gestureLabel = particleFilter.gestureTemplates[ gestureTemplate ].classLabel;
153  gestureIndex = getClassLabelIndexValue( gestureLabel );
154 
155  classDistances[ gestureIndex ] += particleFilter[i].w;
156  }
157 
158  bool rejectPrediction = false;
159  if( useNullRejection ){
160  if( particleFilter.getWeightSum() < 1.0e-5 ){
161  rejectPrediction = true;
162  }
163  }
164 
165  //Compute the class likelihoods
166  for(unsigned int i=0; i<numClasses; i++){
167 
168  classLikelihoods[ i ] = rejectPrediction ? 0 : classDistances[i];
169 
170  if( classLikelihoods[i] > maxLikelihood ){
171  predictedClassLabel = classLabels[i];
172  maxLikelihood = classLikelihoods[i];
173  }
174  }
175 
176  //Estimate the phase
177  phase = particleFilter.getStateEstimation()[1]; //The 2nd element in the state vector is the estimatied phase
178 
179  return true;
180 
181 }
182 
184 
186 
187  particleFilter.clear();
188 
189  return true;
190 }
191 
193 
195 
196  particleFilter.reset();
197 
198  return true;
199 }
200 
201 bool ParticleClassifier::saveModelToFile( std::fstream &file ) const{
202 
203  if(!file.is_open())
204  {
205  errorLog <<"saveModelToFile(fstream &file) - The file is not open!" << std::endl;
206  return false;
207  }
208 
209  return true;
210 }
211 
212 bool ParticleClassifier::loadModelFromFile( std::fstream &file ){
213 
214  clear();
215 
216  if(!file.is_open())
217  {
218  errorLog << "loadModelFromFile(string filename) - Could not open file to load model" << std::endl;
219  return false;
220  }
221 
222  //Flag that the model is trained
223  trained = true;
224 
225  //Resize the prediction results to make sure it is setup for realtime prediction
226  maxLikelihood = DEFAULT_NULL_LIKELIHOOD_VALUE;
227  bestDistance = DEFAULT_NULL_DISTANCE_VALUE;
228  classLikelihoods.resize(numClasses,DEFAULT_NULL_LIKELIHOOD_VALUE);
229  classDistances.resize(numClasses,DEFAULT_NULL_DISTANCE_VALUE);
230 
231  return true;
232 }
233 
234 const Vector< ParticleClassifierGestureTemplate >& ParticleClassifier::getGestureTemplates() const{
235  return particleFilter.gestureTemplates;
236 }
237 
238 const ParticleClassifierParticleFilter& ParticleClassifier::getParticleFilter() const {
239  return particleFilter;
240 }
241 
242 VectorDouble ParticleClassifier::getStateEstimation() const{
243  return particleFilter.getStateEstimation();
244 }
245 
246 Float ParticleClassifier::getPhase() const{
247  if( trained ){
248  return particleFilter.getStateEstimation()[1];
249  }
250  return 0;
251 }
252 
253 Float ParticleClassifier::getVelocity() const{
254  if( trained ){
255  return particleFilter.getStateEstimation()[2];
256  }
257  return 0;
258 }
259 
260 bool ParticleClassifier::setNumParticles(const unsigned int numParticles){
261 
262  clear();
263 
264  this->numParticles = numParticles;
265 
266  return true;
267 }
268 
269 bool ParticleClassifier::setSensorNoise(const unsigned int sensorNoise){
270 
271  clear();
272 
273  this->sensorNoise = sensorNoise;
274 
275  return true;
276 }
277 
278 bool ParticleClassifier::setTransitionSigma(const unsigned int transitionSigma){
279 
280  clear();
281 
282  this->transitionSigma = transitionSigma;
283 
284  return true;
285 }
286 
287 bool ParticleClassifier::setPhaseSigma(const unsigned int phaseSigma){
288 
289  clear();
290 
291  this->phaseSigma = phaseSigma;
292 
293  return true;
294 }
295 
296 bool ParticleClassifier::setVelocitySigma(const unsigned int velocitySigma){
297 
298  clear();
299 
300  this->velocitySigma = velocitySigma;
301 
302  return true;
303 }
304 
305 GRT_END_NAMESPACE
Float getWeightSum() const
#define DEFAULT_NULL_LIKELIHOOD_VALUE
Definition: Classifier.h:38
virtual bool filter(SENSOR_DATA &data)
Float scale(const Float &x, const Float &minSource, const Float &maxSource, const Float &minTarget, const Float &maxTarget, const bool constrain=false)
Definition: MLBase.h:339
virtual ~ParticleClassifier(void)
std::string getClassifierType() const
Definition: Classifier.cpp:160
virtual bool saveModelToFile(std::fstream &file) const
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
UINT getClassLabelIndexValue(UINT classLabel) const
Definition: Classifier.cpp:194
ParticleClassifier & operator=(const ParticleClassifier &rhs)
Vector< ClassTracker > getClassTracker() const
virtual bool loadModelFromFile(std::fstream &file)
virtual bool predict_(VectorFloat &inputVector)
virtual bool train_(TimeSeriesClassificationData &trainingData)
bool copyBaseVariables(const Classifier *classifier)
Definition: Classifier.cpp:92
ParticleClassifier(const unsigned int numParticles=2000, const Float sensorNoise=20.0, const Float transitionSigma=0.005, const Float phaseSigma=0.1, const Float velocitySigma=0.01)
virtual bool reset()
Definition: Classifier.cpp:122
bool scale(const Float minTarget, const Float maxTarget)
virtual bool deepCopyFrom(const Classifier *classifier)
virtual bool clear()
Definition: Classifier.cpp:141
VectorFloat getStateEstimation() const