GestureRecognitionToolkit  Version: 0.2.0
The Gesture Recognition Toolkit (GRT) is a cross-platform, open-source, c++ machine learning library for real-time gesture recognition.
KMeansQuantizer.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 #define GRT_DLL_EXPORTS
22 #include "KMeansQuantizer.h"
23 
24 GRT_BEGIN_NAMESPACE
25 
26 //Register your module with the FeatureExtraction base class
27 RegisterFeatureExtractionModule< KMeansQuantizer > KMeansQuantizer::registerModule("KMeansQuantizer");
28 
29 KMeansQuantizer::KMeansQuantizer(const UINT numClusters){
30 
31  this->numClusters = numClusters;
32  classType = "KMeansQuantizer";
33  featureExtractionType = classType;
34 
35  debugLog.setProceedingText("[DEBUG KMeansQuantizer]");
36  errorLog.setProceedingText("[ERROR KMeansQuantizer]");
37  warningLog.setProceedingText("[WARNING KMeansQuantizer]");
38 }
39 
41 
42  classType = "KMeansQuantizer";
43  featureExtractionType = classType;
44 
45  debugLog.setProceedingText("[DEBUG KMeansQuantizer]");
46  errorLog.setProceedingText("[ERROR KMeansQuantizer]");
47  warningLog.setProceedingText("[WARNING KMeansQuantizer]");
48 
49  //Invoke the equals operator to copy the data from the rhs instance to this instance
50  *this = rhs;
51 }
52 
54 }
55 
57  if(this!=&rhs){
58  //Copy any class variables from the rhs instance to this instance
59  this->numClusters = rhs.numClusters;
60  this->clusters = rhs.clusters;
61  this->quantizationDistances = rhs.quantizationDistances;
62 
63  //Copy the base variables
65  }
66  return *this;
67 }
68 
69 bool KMeansQuantizer::deepCopyFrom(const FeatureExtraction *featureExtraction){
70 
71  if( featureExtraction == NULL ) return false;
72 
73  if( this->getFeatureExtractionType() == featureExtraction->getFeatureExtractionType() ){
74 
75  //Cast the feature extraction pointer to a pointer to your custom feature extraction module
76  //Then invoke the equals operator
77  *this = *(KMeansQuantizer*)featureExtraction;
78 
79  return true;
80  }
81 
82  errorLog << "clone(FeatureExtraction *featureExtraction) - FeatureExtraction Types Do Not Match!" << std::endl;
83 
84  return false;
85 }
86 
88 
89  //Run the quantize algorithm
90  quantize( inputVector );
91 
92  return true;
93 }
94 
96 
98 
99  if( trained ){
100  std::fill(quantizationDistances.begin(),quantizationDistances.end(),0);
101  }
102 
103  return true;
104 }
105 
107 
109 
110  clusters.clear();
111  quantizationDistances.clear();
112  quantizationDistances.clear();
113 
114  return true;
115 }
116 
117 bool KMeansQuantizer::saveModelToFile( std::fstream &file ) const{
118 
119  if( !file.is_open() ){
120  errorLog << "saveModelToFile(fstream &file) - The file is not open!" << std::endl;
121  return false;
122  }
123 
124  //Save the header
125  file << "KMEANS_QUANTIZER_FILE_V1.0" << std::endl;
126 
127  //Save the feature extraction base class settings
129  errorLog << "saveModelToFile(fstream &file) - Failed to save base feature extraction settings to file!" << std::endl;
130  return false;
131  }
132 
133  //Save the KMeansQuantizer settings
134  file << "QuantizerTrained: " << trained << std::endl;
135  file << "NumClusters: " << numClusters << std::endl;
136 
137  if( trained ){
138  file << "Clusters: \n";
139  for(UINT k=0; k<numClusters; k++){
140  for(UINT j=0; j<numInputDimensions; j++){
141  file << clusters[k][j];
142  if( j != numInputDimensions-1 ) file << "\t";
143  else file << std::endl;
144  }
145  }
146  }
147 
148  return true;
149 }
150 
151 bool KMeansQuantizer::loadModelFromFile( std::fstream &file ){
152 
153  //Clear any previouly built model and settings
154  clear();
155 
156  if( !file.is_open() ){
157  errorLog << "loadModelFromFile(fstream &file) - The file is not open!" << std::endl;
158  return false;
159  }
160 
161  std::string word;
162 
163  //First, you should read and validate the header
164  file >> word;
165  if( word != "KMEANS_QUANTIZER_FILE_V1.0" ){
166  errorLog << "loadModelFromFile(fstream &file) - Invalid file format!" << std::endl;
167  return false;
168  }
169 
170  //Second, you should load the base feature extraction settings to the file
172  errorLog << "loadFeatureExtractionSettingsFromFile(fstream &file) - Failed to load base feature extraction settings from file!" << std::endl;
173  return false;
174  }
175 
176  file >> word;
177  if( word != "QuantizerTrained:" ){
178  errorLog << "loadModelFromFile(fstream &file) - Failed to load QuantizerTrained!" << std::endl;
179  return false;
180  }
181  file >> trained;
182 
183  file >> word;
184  if( word != "NumClusters:" ){
185  errorLog << "loadModelFromFile(fstream &file) - Failed to load NumClusters!" << std::endl;
186  return false;
187  }
188  file >> numClusters;
189 
190  if( trained ){
191  clusters.resize(numClusters, numInputDimensions);
192  file >> word;
193  if( word != "Clusters:" ){
194  errorLog << "loadModelFromFile(fstream &file) - Failed to load Clusters!" << std::endl;
195  return false;
196  }
197 
198  for(UINT k=0; k<numClusters; k++){
199  for(UINT j=0; j<numInputDimensions; j++){
200  file >> clusters[k][j];
201  }
202  }
203 
204  initialized = true;
205  featureDataReady = false;
206  quantizationDistances.resize(numClusters,0);
207  }
208 
209  return true;
210 }
211 
213  MatrixFloat data = trainingData.getDataAsMatrixFloat();
214  return train( data );
215 }
216 
218  MatrixFloat data = trainingData.getDataAsMatrixFloat();
219  return train( data );
220 }
221 
223  MatrixFloat data = trainingData.getDataAsMatrixFloat();
224  return train( data );
225 }
226 
228  MatrixFloat data = trainingData.getDataAsMatrixFloat();
229  return train( data );
230 }
231 
233 
234  //Clear any previous model
235  clear();
236 
237  //Train the KMeans model
238  KMeans kmeans;
239  kmeans.setNumClusters(numClusters);
240  kmeans.setComputeTheta( true );
241  kmeans.setMinChange( minChange );
242  kmeans.setMinNumEpochs( minNumEpochs );
243  kmeans.setMaxNumEpochs( maxNumEpochs );
244 
245  if( !kmeans.train_(trainingData) ){
246  errorLog << "train_(MatrixFloat &trainingData) - Failed to train quantizer!" << std::endl;
247  return false;
248  }
249 
250  trained = true;
251  initialized = true;
252  numInputDimensions = trainingData.getNumCols();
253  numOutputDimensions = 1; //This is always 1 for the KMeansQuantizer
254  featureVector.resize(numOutputDimensions,0);
255  clusters = kmeans.getClusters();
256  quantizationDistances.resize(numClusters,0);
257 
258  return true;
259 }
260 
261 UINT KMeansQuantizer::quantize(Float inputValue){
262  return quantize( VectorFloat(1,inputValue) );
263 }
264 
265 UINT KMeansQuantizer::quantize(const VectorFloat &inputVector){
266 
267  if( !trained ){
268  errorLog << "computeFeatures(const VectorFloat &inputVector) - The quantizer has not been trained!" << std::endl;
269  return 0;
270  }
271 
272  if( inputVector.getSize() != numInputDimensions ){
273  errorLog << "computeFeatures(const VectorFloat &inputVector) - The size of the inputVector (" << inputVector.getSize() << ") does not match that of the filter (" << numInputDimensions << ")!" << std::endl;
274  return 0;
275  }
276 
277  //Find the minimum cluster
278  Float minDist = grt_numeric_limits< Float >::max();
279  UINT quantizedValue = 0;
280 
281  for(UINT k=0; k<numClusters; k++){
282  //Compute the squared Euclidean distance
283  quantizationDistances[k] = 0;
284  for(UINT i=0; i<numInputDimensions; i++){
285  quantizationDistances[k] += grt_sqr( inputVector[i]-clusters[k][i] );
286  }
287  if( quantizationDistances[k] < minDist ){
288  minDist = quantizationDistances[k];
289  quantizedValue = k;
290  }
291  }
292 
293  featureVector[0] = quantizedValue;
294  featureDataReady = true;
295 
296  return quantizedValue;
297 }
298 
300  return numClusters;
301 }
302 
303 bool KMeansQuantizer::setNumClusters(const UINT numClusters){
304  clear();
305  this->numClusters = numClusters;
306  return true;
307 }
308 
309 GRT_END_NAMESPACE
virtual bool train_(ClassificationData &trainingData)
void clear()
Definition: Matrix.h:522
virtual bool computeFeatures(const VectorFloat &inputVector)
virtual bool reset()
KMeansQuantizer(const UINT numClusters=10)
bool saveFeatureExtractionSettingsToFile(std::fstream &file) const
MatrixFloat getDataAsMatrixFloat() const
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
virtual bool train_(MatrixFloat &data)
Definition: KMeans.cpp:163
virtual bool train(ClassificationData trainingData)
Definition: MLBase.cpp:89
UINT getSize() const
Definition: Vector.h:191
virtual bool deepCopyFrom(const FeatureExtraction *featureExtraction)
bool setMinChange(const Float minChange)
Definition: MLBase.cpp:287
virtual bool saveModelToFile(std::fstream &file) const
std::string getFeatureExtractionType() const
virtual bool reset()
bool setNumClusters(const UINT numClusters)
UINT quantize(Float inputValue)
The KMeansQuantizer module quantizes the N-dimensional input vector to a 1-dimensional discrete value...
MatrixFloat getDataAsMatrixFloat() const
unsigned int getNumCols() const
Definition: Matrix.h:549
bool setMinNumEpochs(const UINT minNumEpochs)
Definition: MLBase.cpp:282
UINT getNumClusters() const
virtual bool clear()
bool loadFeatureExtractionSettingsFromFile(std::fstream &file)
virtual ~KMeansQuantizer()
KMeansQuantizer & operator=(const KMeansQuantizer &rhs)
Definition: KMeans.h:41
MatrixFloat getDataAsMatrixFloat() const
virtual bool loadModelFromFile(std::fstream &file)
virtual bool resize(const unsigned int r, const unsigned int c)
Definition: Matrix.h:232
bool copyBaseVariables(const FeatureExtraction *featureExtractionModule)
bool setMaxNumEpochs(const UINT maxNumEpochs)
Definition: MLBase.cpp:273
bool setNumClusters(const UINT numClusters)
Definition: Clusterer.cpp:266