📄 somlayer.cpp
字号:
//www.timestocome.com//software@timestocome.com//////This program is a C/C++ program demonstrating the //self organizing network (map) {algorithm by Kohonen}//This is an unsupervised network//one neurode in the output layer will //be activated for each different input pattern//The activated node will be the one whose weight//vector is closest to the input vector////It reads in a data file of vectors in the format://99.99 88.88 77.77 //66.66 55.55 44.44////algorithm//weight array is created (number of input dimensions) X (number of input dimensions * number of vectors)//the weights are initialized to a random number between 0 and 1//weight vectors are normalized//the learning rate is set to one and linearly decremented depending on maximum number of iterations//the neighborhood size is set to the max allowed by the kohonen out put layer size // and decremented linearly depending on the maximum number of iterations//the input vector is normalized//each input is multiplied by a connecting weight and sent to each output node//the inputs for each output node are summed//the winning node is set to one//the outer output nodes are set to zero//the distance between the winning node and the input vector are checked//if the distance is not inside minimum acceptable the weights are adjusted// Wnew = Wold + trainingConstant * (input - Wold)//the nieghborhood size and training constant are decreased////and the next loop is begun.#ifndef _LAYER_CPP#define _LAYER_CPP#include <iostream.h>#include <stdlib.h>#include <math.h>#include <time.h>#include <stdio.h>#include <string>#define MAX_DIMENSIONS 100#define MAX_VECTORS 100class network{private: int vectorsIn, weightColumn; int nodesIn, nodesK; char fileIn[128], fileOut[128]; int maxIterations; double distanceTolerance; int decreaseNeighborhoodSize, neighborhoodSize; double decrementLearningConstant, learningConstant; double kohonen[]; double weights[MAX_DIMENSIONS][MAX_DIMENSIONS*MAX_VECTORS]; double inputArray[MAX_VECTORS][MAX_DIMENSIONS]; int winningNode; double distance; int firstLoop; double trackDistance[MAX_VECTORS]; int trackWinner[MAX_VECTORS]; void normalizeWeights() { for ( int i=0; i<vectorsIn; i++){ double total = 0.0; for ( int j=0; j<weightColumn; j++){ total += weights[i][j] * weights[i][j]; } double temp = sqrt(total); for( int k=0; k<weightColumn; k++){ weights[i][k] = weights[i][k] / temp; } } } void normalizeInput() { for ( int i=0; i<vectorsIn; i++){ double total = 0.0; for ( int j=0; j<nodesIn; j++){ total += inputArray[i][j] * inputArray[i][j]; } for( int j=0; j<nodesIn; j++){ inputArray[i][j] = inputArray[i][j] / sqrt(total); } } }public: network(){} ~network(){} void createNetwork() { // initialize weights to a value between 0.0 and 1.0 srand (time(0)); for (int i=0; i<vectorsIn; i++){ for (int j=0; j<weightColumn; j++){ int max = 1; weights[i][j] = (double) rand()/RAND_MAX; } } normalizeWeights(); } void getData() { //get from user // number of input nodes cout << "*****************************************************"<< endl; cout << "* Enter the number of input nodes needed. (This is *"<< endl; cout << "* number of dimensions in your input vector. *"<< endl; cout << "*****************************************************"<< endl; cin >> nodesIn; // number of input vectors cout << "*****************************************************"<< endl; cout << "* Enter the number of vectors to be learned. *"<< endl; cout << "*****************************************************"<< endl; cin >> vectorsIn; // name of input file cout << "*****************************************************"<< endl; cout << "* Enter the name of your input file containing the *"<< endl; cout << "* vectors. *"<< endl; cout << "*****************************************************"<< endl; cin >> fileIn; // name of file to output results to cout << "*****************************************************"<< endl; cout << "* Enter the name of the file for output. *"<< endl; cout << "*****************************************************"<< endl; cin >> fileOut; // distance tolerance cout << "*****************************************************"<< endl; cout << "* Enter the distance tolerance that is acceptable *"<< endl; cout << "*****************************************************"<< endl; cin >> distanceTolerance; // max number of iterations before giving up cout << "*****************************************************"<< endl; cout << "* Enter the maximum iterations for learning cycle *"<< endl; cout << "* before giving up. *"<< endl; cout << "*****************************************************"<< endl; cin >> maxIterations; //determine output layer size & initialize nodesK = nodesIn * vectorsIn; for(int i=0; i<nodesK; i++){ kohonen[i] = 0; } //vectorsIn = nodesIn; weightColumn = nodesIn * vectorsIn; //determine amount to decrease neighborhood size //every so many loops reduce neighborhood size decreaseNeighborhoodSize = (int)maxIterations/nodesK; // and learning constant by each learning iteration decrementLearningConstant = learningConstant/maxIterations; } //user gave us the number of floating numbers per row (dimensions) //and the number of lines (vectors) //only a space is used between the numbers, no commas or other markers. void readInputFile() { FILE *fp = fopen( fileIn, "r"); //read in vectors for (int i=0; i<vectorsIn; i++){ for (int j=0; j<nodesIn; j++){ fscanf ( fp, "%lf", &inputArray[i][j]); } } fclose (fp); normalizeInput(); } void train () { double distance = 0.0; double oldDistance = 0.0; int distanceCount = 0; //for each vector, loop for (int x=0; x<vectorsIn; x++){ cout << "************vector " << x << " *************"<< endl; for ( int q=0; q<nodesIn; q++){ cout << " " << inputArray[x][q]; } cout << endl << endl; //determine initial neighborhood size neighborhoodSize = nodesK; int count = 0; //set initial values that aren't set in createNetwork learningConstant = 1.0; double distance = 0.0; firstLoop = 1; int winningNode = 0; // inner loop // see if outside number iterations = break from inner loop while (count < maxIterations ){ count++; cout << "\n loop number " << count; cout << "\tdistance " << distance; cout << "\twinning node " << winningNode << endl; // multiply input by its weight connecting to each kohonen node // sum total for each node in kohonen layer for ( int i=0; i<nodesIn; i++){// for each input dimension for ( int k=0; k<nodesK; k++){ //for each kohen node kohonen[k] += inputArray[x][i] * weights[i][k]; } } // see which is winning node double winner = 0.0; for( int i=0; i<nodesK; i++){ if (kohonen[i] > winner){ winner = kohonen[i]; winningNode = i; trackWinner[x] = i; } } // set winner to one // set all other outputNodes to zero for( int i=0; i<nodesK; i++){ if( i != winningNode ){ kohonen[i] = 0.0; }else{ kohonen[i] = 1.0; } } // see if in distance tolerance = break from inner loop // we're done with this vector, do next oldDistance = distance; distance = 0.0; for ( int i=0; i<nodesIn; i++){ distance += inputArray[x][i] - weights[i][winningNode]; } distance = sqrt ( distance * distance); trackDistance[x] = distance; if (distance < distanceTolerance){ cout << "Node " << winningNode << " won. " << endl; cout << "Distance is with in tolerance! " << endl; cout << "loop number " << count << endl; break; } //shake things up if distance grows for too long if (distance > oldDistance ){ distanceCount ++; } if (distanceCount > 5){ distanceCount = 0; neighborhoodSize = nodesK; } // reduce neigborhood size int right = nodesK, left = 0; if (( count % decreaseNeighborhoodSize == 0) && (neighborhoodSize > 1)){ neighborhoodSize--; //keep inside weight array bounds if( winningNode > neighborhoodSize ){ left = winningNode - neighborhoodSize; }else{ left = 0; } if ( winningNode + neighborhoodSize < nodesK){ right = winningNode + neighborhoodSize; }else{ right = nodesK; } } // reduce learning constant learningConstant -= decrementLearningConstant; //flip flag firstLoop = 0; // adjust weights Wn = Wo + LC * (input - Wo) // do the whole matrix the first pass and do // only the neighborhood of the winning node on // subsquent passes. for ( int i=left; i<right; i++){ int j=0; for ( j=0; j<nodesIn; j++){ weights[i][j] += learningConstant * (inputArray[i][j] - weights[i][j]); } //keep things from blowing up if (weights[i][j] < 0.0){ weights[i][j] = 0.0; } if( weights[i][j] > 1.0){ weights[i][j] = 1.0; } } // re-normalize weights normalizeWeights(); }//end inner loop count < maxIterations }//end loop for each vector } void print() { //open file FILE *fp = fopen ( fileOut, "w"); //headings fprintf (fp, "\n\n\n data from training run \n"); //print weight array fprintf( fp, "\nWeight Array\n"); for ( int i=0; i<vectorsIn; i++){ fprintf (fp, "\n"); for ( int j=0; j<weightColumn; j++){ fprintf (fp, " %lf ", weights[i][j]); } } //headings fprintf ( fp, "\n\n\n normalized input vectors\t\t winning node\t distance \n"); //print vectors, winning node for each and distance for each for ( int i=0; i<vectorsIn; i++){ //input vector //winning node number //final distance tolerance fprintf( fp, "\n"); for ( int j=0; j<nodesIn; j++){ fprintf ( fp, " %lf ", inputArray[i][j]); } fprintf (fp, "\t %d\t %lf ", trackWinner[i], trackDistance[i]); } //close output file fclose(fp); }};#endif // _LAYER_CPP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -