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