GestureRecognitionToolkit  Version: 0.2.5
The Gesture Recognition Toolkit (GRT) is a cross-platform, open-source, c++ machine learning library for real-time gesture recognition.
SOMQuantizer.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 "SOMQuantizer.h"
23 
24 GRT_BEGIN_NAMESPACE
25 
26 //Define the string that will be used to identify the object
27 std::string SOMQuantizer::id = "SOMQuantizer";
28 std::string SOMQuantizer::getId() { return SOMQuantizer::id; }
29 
30 //Register your module with the FeatureExtraction base class
32 
34 {
35  this->numClusters = numClusters;
36 }
37 
39 {
40  //Invoke the equals operator to copy the data from the rhs instance to this instance
41  *this = rhs;
42 }
43 
45  //Here you should add any specific code to cleanup your custom feature extraction module if needed
46 }
47 
49  if(this!=&rhs){
50  //Here you should copy any class variables from the rhs instance to this instance
51  this->numClusters = rhs.numClusters;
52  this->som = rhs.som;
53  this->quantizationDistances = rhs.quantizationDistances;
54 
55  //Copy the base variables
57  }
58  return *this;
59 }
60 
61 bool SOMQuantizer::deepCopyFrom(const FeatureExtraction *featureExtraction){
62 
63  if( featureExtraction == NULL ) return false;
64 
65  if( this->getId() == featureExtraction->getId() ){
66 
67  //Cast the feature extraction pointer to a pointer to your custom feature extraction module
68  //Then invoke the equals operator
69  *this = *dynamic_cast<const SOMQuantizer*>(featureExtraction);
70 
71  return true;
72  }
73 
74  errorLog << "deepCopyFrom(FeatureExtraction *featureExtraction) - FeatureExtraction Types Do Not Match!" << std::endl;
75 
76  return false;
77 }
78 
79 bool SOMQuantizer::computeFeatures(const VectorFloat &inputVector){
80 
81  //Run the quantize algorithm
82  quantize( inputVector );
83 
84  return true;
85 }
86 
88 
89  //Reset the base class
91 
92  if( trained ){
93  som.reset();
94  std::fill(quantizationDistances.begin(),quantizationDistances.end(),0);
95  }
96 
97  return true;
98 }
99 
101 
102  //Clear the base class
104 
105  som.clear();
106  quantizationDistances.clear();
107 
108  return true;
109 }
110 
111 bool SOMQuantizer::save( std::fstream &file ) const{
112 
113  if( !file.is_open() ){
114  errorLog << "save(fstream &file) - The file is not open!" << std::endl;
115  return false;
116  }
117 
118  //First, you should add a header (with no spaces) e.g.
119  file << "SOM_QUANTIZER_FILE_V1.0" << std::endl;
120 
121  //Second, you should save the base feature extraction settings to the file
123  errorLog << "saveFeatureExtractionSettingsToFile(fstream &file) - Failed to save base feature extraction settings to file!" << std::endl;
124  return false;
125  }
126 
127  file << "QuantizerTrained: " << trained << std::endl;
128  file << "NumClusters: " << numClusters << std::endl;
129 
130  if( trained ){
131  file << "SOM: \n";
132  if( !som.save( file ) ){
133  errorLog << "save(fstream &file) - Failed to save SelfOrganizingMap settings to file!" << std::endl;
134  return false;
135  }
136  }
137 
138  return true;
139 }
140 
141 bool SOMQuantizer::load( std::fstream &file ){
142 
143  //Clear any previous model
144  clear();
145 
146  if( !file.is_open() ){
147  errorLog << "load(fstream &file) - The file is not open!" << std::endl;
148  return false;
149  }
150 
151  std::string word;
152 
153  //First, you should read and validate the header
154  file >> word;
155  if( word != "SOM_QUANTIZER_FILE_V1.0" ){
156  errorLog << "load(fstream &file) - Invalid file format!" << std::endl;
157  return false;
158  }
159 
160  //Second, you should load the base feature extraction settings to the file
162  errorLog << "loadFeatureExtractionSettingsFromFile(fstream &file) - Failed to load base feature extraction settings from file!" << std::endl;
163  return false;
164  }
165 
166  file >> word;
167  if( word != "QuantizerTrained:" ){
168  errorLog << "load(fstream &file) - Failed to load QuantizerTrained!" << std::endl;
169  return false;
170  }
171  file >> trained;
172 
173  file >> word;
174  if( word != "NumClusters:" ){
175  errorLog << "load(fstream &file) - Failed to load NumClusters!" << std::endl;
176  return false;
177  }
178  file >> numClusters;
179 
180  if( trained ){
181  file >> word;
182  if( word != "SOM:" ){
183  errorLog << "load(fstream &file) - Failed to load SOM!" << std::endl;
184  return false;
185  }
186 
187  if( !som.load( file ) ){
188  errorLog << "load(fstream &file) - Failed to load SelfOrganizingMap settings from file!" << std::endl;
189  return false;
190  }
191 
192  initialized = true;
193  featureDataReady = false;
194  quantizationDistances.resize(numClusters,0);
195  }
196 
197  return true;
198 }
199 
201  MatrixFloat data = trainingData.getDataAsMatrixFloat();
202  return train_( data );
203 }
204 
206  MatrixFloat data = trainingData.getDataAsMatrixFloat();
207  return train_( data );
208 }
209 
211  MatrixFloat data = trainingData.getDataAsMatrixFloat();
212  return train_( data );
213 }
214 
216  MatrixFloat data = trainingData.getDataAsMatrixFloat();
217  return train_( data );
218 }
219 
220 bool SOMQuantizer::train_(MatrixFloat &trainingData){
221 
222  //Clear any previous model
223  clear();
224 
225  if( trainingData.getNumRows() == 0 ){
226  errorLog << "train_(MatrixFloat &trainingData) - Failed to train quantizer, the training data is empty!" << std::endl;
227  return false;
228  }
229 
230  //Train the SOM model
231  som.setNetworkSize( numClusters );
232  som.setNetworkTypology( SelfOrganizingMap::RANDOM_NETWORK );
233  som.setAlphaStart( 0.5 );
234  som.setAlphaEnd( 0.1 );
235  som.setMaxNumEpochs( 1000 );
236 
237  if( !som.train_( trainingData ) ){
238  errorLog << "train(MatrixFloat &trainingData) - Failed to train quantizer!" << std::endl;
239  return false;
240  }
241 
242  //Flag that the feature extraction module is now initialized
243  initialized = true;
244  trained = true;
245  numInputDimensions = trainingData.getNumCols();
246  numOutputDimensions = 1; //This is always 1 for the SOMQuantizer
247  featureVector.resize(numOutputDimensions,0);
248  quantizationDistances.resize(numClusters,0);
249 
250  return true;
251 }
252 
253 UINT SOMQuantizer::quantize(const Float inputValue){
254  return quantize( VectorFloat(1,inputValue) );
255 }
256 
257 UINT SOMQuantizer::quantize(const VectorFloat &inputVector){
258 
259  if( !trained ){
260  errorLog << "computeFeatures(const VectorFloat &inputVector) - The quantizer model has not been trained!" << std::endl;
261  return 0;
262  }
263 
264  if( inputVector.getSize() != numInputDimensions ){
265  errorLog << "computeFeatures(const VectorFloat &inputVector) - The size of the inputVector (" << inputVector.getSize() << ") does not match that of the filter (" << numInputDimensions << ")!" << std::endl;
266  return 0;
267  }
268 
269  //Pass the input data through the map
270  if( !som.predict( inputVector ) ){
271  errorLog << "computeFeatures(const VectorFloat &inputVector) - Failed to perform map!" << std::endl;
272  return 0;
273  }
274  quantizationDistances = som.getMappedData();
275 
276  //Search for the neuron with the maximum output
277  UINT quantizedValue = 0;
278  Float maxValue = 0;
279  for(UINT k=0; k<numClusters; k++){
280  if( quantizationDistances[k] > maxValue ){
281  maxValue = quantizationDistances[k];
282  quantizedValue = k;
283  }
284  }
285 
286  featureVector[0] = quantizedValue;
287  featureDataReady = true;
288 
289  return quantizedValue;
290 }
291 
293  return trained;
294 }
295 
297  return numClusters;
298 }
299 
301  return (trained ? static_cast<UINT>(featureVector[0]) : 0);
302 }
303 
305  return quantizationDistances;
306 }
307 
309  return som;
310 }
311 
312 bool SOMQuantizer::setNumClusters(const UINT numClusters){
313  clear();
314  this->numClusters = numClusters;
315  return true;
316 }
317 
318 GRT_END_NAMESPACE
std::string getId() const
Definition: GRTBase.cpp:85
UINT quantize(const Float inputValue)
virtual bool predict(VectorFloat inputVector)
Definition: MLBase.cpp:135
virtual bool train_(ClassificationData &trainingData)
bool setNumClusters(const UINT numClusters)
VectorFloat getQuantizationDistances() const
virtual bool reset()
Definition: MLBase.cpp:147
virtual bool load(std::fstream &file)
bool saveFeatureExtractionSettingsToFile(std::fstream &file) const
virtual bool load(std::fstream &file)
virtual bool computeFeatures(const VectorFloat &inputVector)
MatrixFloat getDataAsMatrixFloat() const
The SOMQuantizer module quantizes the N-dimensional input vector to a 1-dimensional discrete value...
virtual bool save(std::fstream &file) const
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
virtual bool train_(MatrixFloat &trainingData)
UINT getSize() const
Definition: Vector.h:201
bool getQuantizerTrained() const
SOMQuantizer(const UINT numClusters=10)
virtual bool deepCopyFrom(const FeatureExtraction *featureExtraction)
static std::string getId()
virtual bool clear()
virtual ~SOMQuantizer()
unsigned int getNumRows() const
Definition: Matrix.h:574
MatrixFloat getDataAsMatrixFloat() const
SelfOrganizingMap getSelfOrganizingMap() const
unsigned int getNumCols() const
Definition: Matrix.h:581
bool loadFeatureExtractionSettingsFromFile(std::fstream &file)
SOMQuantizer & operator=(const SOMQuantizer &rhs)
MatrixFloat getDataAsMatrixFloat() const
virtual bool reset()
bool copyBaseVariables(const FeatureExtraction *featureExtractionModule)
virtual bool clear() override
bool setMaxNumEpochs(const UINT maxNumEpochs)
Definition: MLBase.cpp:320
virtual bool save(std::fstream &file) const
UINT getNumClusters() const
UINT getQuantizedValue() const