28 RegisterClustererModule< SelfOrganizingMap > SelfOrganizingMap::registerModule(
"SelfOrganizingMap");
30 SelfOrganizingMap::SelfOrganizingMap(
const UINT networkSize,
const UINT networkTypology,
const UINT maxNumEpochs,
const double alphaStart,
const double alphaEnd ){
32 this->numClusters = networkSize;
33 this->networkTypology = networkTypology;
34 this->maxNumEpochs = maxNumEpochs;
35 this->alphaStart = alphaStart;
36 this->alphaEnd = alphaEnd;
38 classType =
"SelfOrganizingMap";
39 clustererType = classType;
40 debugLog.setProceedingText(
"[DEBUG SelfOrganizingMap]");
41 errorLog.setProceedingText(
"[ERROR SelfOrganizingMap]");
42 trainingLog.setProceedingText(
"[TRAINING SelfOrganizingMap]");
43 warningLog.setProceedingText(
"[WARNING SelfOrganizingMap]");
48 classType =
"SelfOrganizingMap";
49 clustererType = classType;
50 debugLog.setProceedingText(
"[DEBUG KMeans]");
51 errorLog.setProceedingText(
"[ERROR KMeans]");
52 trainingLog.setProceedingText(
"[TRAINING KMeans]");
53 warningLog.setProceedingText(
"[WARNING KMeans]");
57 this->networkTypology = rhs.networkTypology;
58 this->alphaStart = rhs.alphaStart;
59 this->alphaEnd = rhs.alphaEnd;
66 SelfOrganizingMap::~SelfOrganizingMap(){
74 this->networkTypology = rhs.networkTypology;
75 this->alphaStart = rhs.alphaStart;
76 this->alphaEnd = rhs.alphaEnd;
85 bool SelfOrganizingMap::deepCopyFrom(
const Clusterer *clusterer){
87 if( clusterer == NULL )
return false;
93 this->networkTypology = ptr->networkTypology;
94 this->alphaStart = ptr->alphaStart;
95 this->alphaEnd = ptr->alphaEnd;
98 return copyBaseVariables( clusterer );
104 bool SelfOrganizingMap::reset(){
112 bool SelfOrganizingMap::clear(){
119 networkWeights.clear();
131 numInputDimensions = N;
132 numOutputDimensions = numClusters;
136 neurons.resize( numClusters );
138 if( neurons.size() != numClusters ){
139 errorLog <<
"train_( MatrixDouble &data ) - Failed to resize neurons vector, there might not be enough memory!" << endl;
143 for(UINT j=0; j<numClusters; j++){
146 neurons[j].init( N, 0.5 );
153 switch( networkTypology ){
155 networkWeights.resize(numClusters, numClusters);
158 for(UINT i=0; i<numClusters; i++){
159 networkWeights[i][i] = 1;
166 for(UINT i=0; i<numClusters*numClusters; i++){
171 if( indexA != indexB ){
176 networkWeights[indexA][indexB] = weight;
177 networkWeights[indexB][indexA] = weight;
186 for(UINT i=0; i<M; i++){
187 for(UINT j=0; j<numInputDimensions; j++){
188 data[i][j] = scale(data[i][j],ranges[j].minValue,ranges[j].maxValue,0,1);
194 double lastError = 0;
195 double trainingSampleError = 0;
197 double minChange = 0;
198 double weightUpdate = 0;
199 double weightUpdateSum = 0;
201 double neuronDiff = 0;
203 bool keepTraining =
true;
204 VectorDouble trainingSample;
205 vector< UINT > randomTrainingOrder(M);
210 for(UINT i=0; i<M; i++){
211 randomTrainingOrder[i] = i;
213 std::random_shuffle(randomTrainingOrder.begin(), randomTrainingOrder.end());
216 while( keepTraining ){
219 alpha = Util::scale(iter,0,maxNumEpochs,alphaStart,alphaEnd);
223 for(UINT i=0; i<M; i++){
225 trainingSampleError = 0;
228 trainingSample = data.
getRowVector( randomTrainingOrder[i] );
232 double bestDist = numeric_limits<double>::max();
234 for(UINT j=0; j<numClusters; j++){
235 dist = neurons[j].getSquaredWeightDistance( trainingSample );
236 if( dist < bestDist ){
244 for(UINT j=0; j<numClusters; j++){
249 for(UINT n=0; n<N; n++){
250 neuronDiff = trainingSample[n] - neurons[j][n];
251 weightUpdate = networkWeights[bestIndex][j] * alpha * neuronDiff;
252 neurons[j][n] += weightUpdate;
253 weightUpdateSum += neuronDiff;
256 trainingSampleError += SQR( weightUpdateSum );
259 error += sqrt( trainingSampleError / numClusters );
263 delta = fabs( error-lastError );
267 if( delta <= minChange ){
269 keepTraining =
false;
272 if( grt_isinf( error ) ){
273 errorLog <<
"train_(MatrixDouble &data) - Training failed! Error is NAN!" << endl;
277 if( ++iter >= maxNumEpochs ){
278 keepTraining =
false;
281 trainingLog <<
"Epoch: " << iter <<
" Squared Error: " << error <<
" Delta: " << delta <<
" Alpha: " << alpha << endl;
284 numTrainingIterationsToConverge = iter;
300 bool SelfOrganizingMap::map_( VectorDouble &x ){
307 for(UINT i=0; i<numInputDimensions; i++){
308 x[i] = scale(x[i], ranges[i].minValue, ranges[i].maxValue, 0, 1);
312 if( mappedData.size() != numClusters )
313 mappedData.resize( numClusters );
315 for(UINT i=0; i<numClusters; i++){
316 mappedData[i] = neurons[i].fire( x );
322 bool SelfOrganizingMap::saveModelToFile(fstream &file)
const{
325 errorLog <<
"saveModelToFile(fstream &file) - Can't save model to file, the model has not been trained!" << endl;
329 file <<
"GRT_SELF_ORGANIZING_MAP_MODEL_FILE_V1.0\n";
331 if( !saveClustererSettingsToFile( file ) ){
332 errorLog <<
"saveModelToFile(fstream &file) - Failed to save cluster settings to file!" << endl;
336 file <<
"NetworkTypology: " << networkTypology << endl;
337 file <<
"AlphaStart: " << alphaStart <<endl;
338 file <<
"AlphaEnd: " << alphaEnd <<endl;
341 file <<
"NetworkWeights: \n";
342 for(UINT i=0; i<networkWeights.getNumRows(); i++){
343 for(UINT j=0; j<networkWeights.getNumCols(); j++){
344 file << networkWeights[i][j];
345 if( j<networkWeights.getNumCols()-1 ) file <<
"\t";
350 file <<
"Neurons: \n";
351 for(UINT i=0; i<neurons.size(); i++){
352 if( !neurons[i].saveNeuronToFile( file ) ){
353 errorLog <<
"saveModelToFile(fstream &file) - Failed to save neuron to file!" << endl;
363 bool SelfOrganizingMap::loadModelFromFile(fstream &file){
370 if( word !=
"GRT_SELF_ORGANIZING_MAP_MODEL_FILE_V1.0" ){
371 errorLog <<
"loadModelFromFile(fstream &file) - Failed to load file header!" << endl;
375 if( !loadClustererSettingsFromFile( file ) ){
376 errorLog <<
"loadModelFromFile(fstream &file) - Failed to load cluster settings from file!" << endl;
381 if( word !=
"NetworkTypology:" ){
382 errorLog <<
"loadModelFromFile(fstream &file) - Failed to load NetworkTypology header!" << endl;
385 file >> networkTypology;
388 if( word !=
"AlphaStart:" ){
389 errorLog <<
"loadModelFromFile(fstream &file) - Failed to load AlphaStart header!" << endl;
395 if( word !=
"AlphaEnd:" ){
396 errorLog <<
"loadModelFromFile(fstream &file) - Failed to load alphaEnd header!" << endl;
404 if( word !=
"NetworkWeights:" ){
405 errorLog <<
"loadModelFromFile(fstream &file) - Failed to load NetworkWeights header!" << endl;
409 networkWeights.resize(numClusters, numClusters);
410 for(UINT i=0; i<networkWeights.getNumRows(); i++){
411 for(UINT j=0; j<networkWeights.getNumCols(); j++){
412 file >> networkWeights[i][j];
417 if( word !=
"Neurons:" ){
418 errorLog <<
"loadModelFromFile(fstream &file) - Failed to load Neurons header!" << endl;
422 neurons.resize(numClusters);
423 for(UINT i=0; i<neurons.size(); i++){
424 if( !neurons[i].loadNeuronFromFile( file ) ){
425 errorLog <<
"loadModelFromFile(fstream &file) - Failed to save neuron to file!" << endl;
434 bool SelfOrganizingMap::validateNetworkTypology(
const UINT networkTypology ){
435 if( networkTypology == RANDOM_NETWORK )
return true;
437 warningLog <<
"validateNetworkTypology(const UINT networkTypology) - Unknown networkTypology!" << endl;
442 UINT SelfOrganizingMap::getNetworkSize()
const{
446 double SelfOrganizingMap::getAlphaStart()
const{
450 double SelfOrganizingMap::getAlphaEnd()
const{
454 VectorDouble SelfOrganizingMap::getMappedData()
const{
458 vector< GaussNeuron > SelfOrganizingMap::getNeurons()
const{
462 const vector< GaussNeuron >& SelfOrganizingMap::getNeuronsRef()
const{
466 MatrixDouble SelfOrganizingMap::getNetworkWeights()
const{
467 return networkWeights;
470 bool SelfOrganizingMap::setNetworkSize(
const UINT networkSize ){
471 if( networkSize > 0 ){
472 this->numClusters = networkSize;
476 warningLog <<
"setNetworkSize(const UINT networkSize) - The networkSize must be greater than 0!" << endl;
481 bool SelfOrganizingMap::setNetworkTypology(
const UINT networkTypology ){
482 if( validateNetworkTypology( networkTypology ) ){
483 this->networkTypology = networkTypology;
489 bool SelfOrganizingMap::setAlphaStart(
const double alphaStart ){
491 if( alphaStart > 0 ){
492 this->alphaStart = alphaStart;
496 warningLog <<
"setAlphaStart(const double alphaStart) - AlphaStart must be greater than zero!" << endl;
501 bool SelfOrganizingMap::setAlphaEnd(
const double alphaEnd ){
504 this->alphaEnd = alphaEnd;
508 warningLog <<
"setAlphaEnd(const double alphaEnd) - AlphaEnd must be greater than zero!" << endl;
This class implements the Self Oganizing Map clustering algorithm.
unsigned int getNumCols() const
string getClustererType() const
MatrixDouble getDataAsMatrixDouble() const
int getRandomNumberInt(int minRange, int maxRange)
double getRandomNumberUniform(double minRange=0.0, double maxRange=1.0)
MatrixDouble getDataAsMatrixDouble() const
unsigned int getNumRows() const
std::vector< MinMax > getRanges() const
std::vector< T > getRowVector(const unsigned int r) const