21 #define GRT_DLL_EXPORTS 26 #define SOM_MIN_TARGET -1.0 27 #define SOM_MAX_TARGET 1.0 30 const std::string SelfOrganizingMap::id =
"SelfOrganizingMap";
39 this->networkTypology = networkTypology;
40 this->maxNumEpochs = maxNumEpochs;
41 this->sigmaWeight = sigmaWeight;
42 this->alphaStart = alphaStart;
43 this->alphaEnd = alphaEnd;
51 this->networkTypology = rhs.networkTypology;
52 this->sigmaWeight = rhs.sigmaWeight;
53 this->alphaStart = rhs.alphaStart;
54 this->alphaEnd = rhs.alphaEnd;
55 this->neurons = rhs.neurons;
56 this->mappedData = rhs.mappedData;
72 this->networkTypology = rhs.networkTypology;
73 this->sigmaWeight = rhs.sigmaWeight;
74 this->alphaStart = rhs.alphaStart;
75 this->alphaEnd = rhs.alphaEnd;
76 this->neurons = rhs.neurons;
77 this->mappedData = rhs.mappedData;
88 if( clusterer == NULL )
return false;
95 this->networkTypology = ptr->networkTypology;
96 this->sigmaWeight = ptr->sigmaWeight;
97 this->alphaStart = ptr->alphaStart;
98 this->alphaEnd = ptr->alphaEnd;
99 this->neurons = ptr->neurons;
100 this->mappedData = ptr->mappedData;
135 numInputDimensions = N;
140 neurons.
resize( numClusters, numClusters );
143 errorLog <<
"train_( MatrixFloat &data ) - Failed to resize neurons matrix, there might not be enough memory!" << std::endl;
150 neurons[i][j].init( N, 0.5, SOM_MIN_TARGET, SOM_MAX_TARGET );
157 for(UINT i=0; i<M; i++){
158 for(UINT j=0; j<numInputDimensions; j++){
159 data[i][j] =
scale(data[i][j],ranges[j].minValue,ranges[j].maxValue,SOM_MIN_TARGET,SOM_MAX_TARGET);
166 Float trainingSampleError = 0;
169 Float weightUpdate = 0;
171 Float neuronDiff = 0;
172 Float neuronWeightFunction = 0;
175 bool keepTraining =
true;
182 for(UINT i=0; i<M; i++){
183 randomTrainingOrder[i] = i;
185 std::random_shuffle(randomTrainingOrder.begin(), randomTrainingOrder.end());
188 while( keepTraining ){
191 alpha =
Util::scale(iter,0,maxNumEpochs,alphaStart,alphaEnd);
195 for(UINT m=0; m<M; m++){
197 trainingSampleError = 0;
200 trainingSample = data.
getRowVector( randomTrainingOrder[m] );
205 UINT bestIndexRow = 0;
206 UINT bestIndexCol = 0;
209 dist = neurons[i][j].getSquaredWeightDistance( trainingSample );
210 if( dist < bestDist ){
221 const Float bir = bestIndexRow;
222 const Float bic = bestIndexCol;
228 gamma = 2.0 * grt_sqr( numClusters * sigmaWeight );
229 neuronWeightFunction = exp( -grt_sqr(bir-i)/gamma ) * exp( -grt_sqr(bic-j)/gamma );
231 for(UINT n=0; n<N; n++){
232 neuronDiff = trainingSample[n] - neurons[i][j][n];
233 weightUpdate = neuronWeightFunction * alpha * neuronDiff;
234 neurons[i][j][n] += weightUpdate;
242 trainingLog <<
"iter: " << iter <<
" average error: " << error << std::endl;
245 delta = fabs( error-lastError );
249 if( delta <= minChange &&
false ){
251 keepTraining =
false;
254 if( grt_isinf( error ) ){
255 errorLog <<
"train_(MatrixFloat &data) - Training failed! Error is NAN!" << std::endl;
259 if( ++iter >= maxNumEpochs ){
260 keepTraining =
false;
263 trainingLog <<
"Epoch: " << iter <<
" Squared Error: " << error <<
" Delta: " << delta <<
" Alpha: " << alpha << std::endl;
266 numTrainingIterationsToConverge = iter;
289 for(UINT i=0; i<numInputDimensions; i++){
290 x[i] =
scale(x[i], ranges[i].minValue, ranges[i].maxValue, SOM_MIN_TARGET, SOM_MAX_TARGET);
300 mappedData[index++] = neurons[i][j].fire( x );
310 errorLog <<
"save(fstream &file) - Can't save model to file, the model has not been trained!" << std::endl;
314 file <<
"GRT_SELF_ORGANIZING_MAP_MODEL_FILE_V1.0\n";
317 errorLog <<
"save(fstream &file) - Failed to save cluster settings to file!" << std::endl;
321 file <<
"NetworkTypology: " << networkTypology << std::endl;
322 file <<
"AlphaStart: " << alphaStart << std::endl;
323 file <<
"AlphaEnd: " << alphaEnd << std::endl;
326 file <<
"Neurons: \n";
329 if( !neurons[i][j].
save( file ) ){
330 errorLog <<
"save(fstream &file) - Failed to save neuron to file!" << std::endl;
348 if( word !=
"GRT_SELF_ORGANIZING_MAP_MODEL_FILE_V1.0" ){
349 errorLog <<
"load(fstream &file) - Failed to load file header!" << std::endl;
354 errorLog <<
"load(fstream &file) - Failed to load cluster settings from file!" << std::endl;
359 if( word !=
"NetworkTypology:" ){
360 errorLog <<
"load(fstream &file) - Failed to load NetworkTypology header!" << std::endl;
363 file >> networkTypology;
366 if( word !=
"AlphaStart:" ){
367 errorLog <<
"load(fstream &file) - Failed to load AlphaStart header!" << std::endl;
373 if( word !=
"AlphaEnd:" ){
374 errorLog <<
"load(fstream &file) - Failed to load alphaEnd header!" << std::endl;
382 if( word !=
"Neurons:" ){
383 errorLog <<
"load(fstream &file) - Failed to load Neurons header!" << std::endl;
390 if( !neurons[i][j].
load( file ) ){
391 errorLog <<
"load(fstream &file) - Failed to save neuron to file!" << std::endl;
402 if( networkTypology == RANDOM_NETWORK )
return true;
404 warningLog <<
"validateNetworkTypology(const UINT networkTypology) - Unknown networkTypology!" << std::endl;
413 Float SelfOrganizingMap::getAlphaStart()
const{
417 Float SelfOrganizingMap::getAlphaEnd()
const{
421 VectorFloat SelfOrganizingMap::getMappedData()
const{
439 for(UINT n=0; n<numInputDimensions; n++){
440 weights[i][j][n] = neurons[i][j][n];
447 bool SelfOrganizingMap::setNetworkSize(
const UINT networkSize ){
448 if( networkSize > 0 ){
453 warningLog <<
"setNetworkSize(const UINT networkSize) - The networkSize must be greater than 0!" << std::endl;
458 bool SelfOrganizingMap::setNetworkTypology(
const UINT networkTypology ){
460 this->networkTypology = networkTypology;
466 bool SelfOrganizingMap::setAlphaStart(
const Float alphaStart ){
468 if( alphaStart > 0 ){
469 this->alphaStart = alphaStart;
473 warningLog <<
"setAlphaStart(const Float alphaStart) - AlphaStart must be greater than zero!" << std::endl;
478 bool SelfOrganizingMap::setAlphaEnd(
const Float alphaEnd ){
481 this->alphaEnd = alphaEnd;
485 warningLog <<
"setAlphaEnd(const Float alphaEnd) - AlphaEnd must be greater than zero!" << std::endl;
490 bool SelfOrganizingMap::setSigmaWeight(
const Float sigmaWeight ){
492 if( sigmaWeight > 0 ){
493 this->sigmaWeight = sigmaWeight;
497 warningLog <<
"setSigmaWeight(const Float sigmaWeight) - sigmaWeight must be greater than zero!" << std::endl;
static std::string getId()
std::string getId() const
unsigned int getSize() const
virtual bool deepCopyFrom(const Clusterer *clusterer)
virtual bool reset() override
virtual bool train_(UnlabelledData &trainingData)
This class implements the Self Oganizing Map clustering algorithm.
static Float scale(const Float &x, const Float &minSource, const Float &maxSource, const Float &minTarget, const Float &maxTarget, const bool constrain=false)
This file contains the Random class, a useful wrapper for generating cross platform random functions...
virtual bool load(std::fstream &file)
MatrixFloat getDataAsMatrixFloat() const
virtual bool save(std::fstream &file) const
virtual bool clear() override
virtual bool resize(const unsigned int size)
virtual bool train_(MatrixFloat &trainingData)
UINT getNetworkSize() const
bool copyBaseVariables(const Clusterer *clusterer)
bool validateNetworkTypology(const UINT networkTypology)
bool loadClustererSettingsFromFile(std::fstream &file)
SelfOrganizingMap(const UINT networkSize=5, const UINT networkTypology=RANDOM_NETWORK, const UINT maxNumEpochs=1000, const Float sigmaWeight=0.2, const Float alphaStart=0.3, const Float alphaEnd=0.1)
virtual bool map_(VectorFloat &x)
bool saveClustererSettingsToFile(std::fstream &file) const
Vector< T > getRowVector(const unsigned int r) const
UINT numClusters
Number of clusters in the model.
unsigned int getNumRows() const
unsigned int getNumCols() const
Vector< MinMax > getRanges() const
MatrixFloat getDataAsMatrixFloat() const
virtual bool resize(const unsigned int r, const unsigned int c)
virtual ~SelfOrganizingMap()
SelfOrganizingMap & operator=(const SelfOrganizingMap &rhs)
Float scale(const Float &x, const Float &minSource, const Float &maxSource, const Float &minTarget, const Float &maxTarget, const bool constrain=false)