// // neural_ga.cpp //This code uses a genetic algorithm to train a //single-hidden-layer feedfoward artificial neural network. // //The user specifices a data file containing training vectors of the form //(input1, input2, ... , inputn, output1, output2, ... , outputn). The file //must be ASCII text format, with spaces separating the components of each //vector, and hard returns separating the vectors. //The user defines the number of nodes in each layer of the network. // //The genome for each individual is a series of floating point numbers //representing weights on the output nodes and then on the hidden nodes. The //genetic algorithm (after Montana and Davis) uses fitness-proportionate //selection, multipoint crossover which keeps weights on each node together, //and mutatation. The mutation operator adds //a small random number to each weight selected for mutation. // //The training vectors are split (80/20) into a training set and a test set. //The training set data are used to evolve the population; at the end of //training (based only on completing the specified number of generations) //the most fit individual is selected using the test set, and the weight values //this individual are written into a file entitled "trainw.dat". // //This code is written as a Windows console application. Removing the conio.h //include and the getch() statements will make it generic. // // //Copyright 1998 Michael J. Wax //You may use this code as is, or incorporate it in another program, //as long as proper attribution is given. However, I make no warranties, //express or implied, regarding the performance of this code, its freedom from //error, or its suitability for use in a given application. // // #include #include #include #include #include #include #include //use 80% of training vectors for training, 20% for testing class node { public: double *weight, output; //constructor node () {} double calcout (double &activation){ return 1/(1+exp(-activation)); } }; class hiddennode : public node { }; class outputnode : public node { }; class datavector { public: double *vinput, *voutput; }; class chromosome { public: double fitness, *gene; //constructor initializes gene chromosome () {} //mutation function - adds random number between -1 and 1 to gene //probability of mutation on each gene is 0.01 void mutate (int gene_number) { if (double (rand()) / double (RAND_MAX) < 0.01) { gene[gene_number] += 2 * (double (rand()) / double (RAND_MAX) - 0.5); } } }; void swap (chromosome list[], int a, int b) { chromosome v; v = list[a]; list[a] = list[b]; list[b] = v; } void quicksort (chromosome list[], int left, int right) { int i, j; chromosome v; if (right > left) { v = list[right]; i = left - 1; j = right; for (;;) { while (list[++i].fitness < v.fitness); while (list[--j].fitness > v.fitness); if (i >= j) break; swap (list, i, j); } swap (list, i, right); quicksort (list, left, i-1); quicksort (list, i+1, right); } } void main() { double scratch, generation_fitness, activation, *wheel, pc = 0.7, sumsquarederror; //crossover probability is 0.7 on each node int counter, counter2, counter3, master, numin, numhidden, numout, num_genes, population, max_generations, generation = 0, numvectors, numtest, individual, individual2; char file_name[15]; datavector *t_vector; hiddennode *hn; outputnode *outn; srand( (unsigned)time( NULL ) ); cout << "File name containing data? "; cin >> file_name; cout << "How many data vectors? "; cin >> numvectors; cout << "Network structure:" << endl; cout << " How many input nodes? "; cin >> numin; cout << " How many hidden nodes? "; cin >> numhidden; cout << " How many output nodes? "; cin >> numout; cout << "How many individuals? "; cin >> population; cout << "How many generations? "; cin >> max_generations; //set up network cout << "Setting up network . . ." << endl; hn = new hiddennode[numhidden]; outn = new outputnode[numout]; for (counter = 0; counter < numhidden; ++counter) { hn[counter].weight = new double[numin]; } for (counter = 0; counter < numout; ++counter) { outn[counter].weight = new double[numhidden]; } //create training vectors and read in from file cout << "Reading in data vectors . . ." << endl; t_vector = new datavector[numvectors]; ifstream training_input (file_name, ios::in); for (counter = 0; counter < numvectors; ++counter) { t_vector[counter].vinput = new double[numin]; t_vector[counter].voutput = new double[numout]; for (counter2 = 0; counter2 < numin; ++counter2) { training_input >> t_vector[counter].vinput[counter2]; } for (counter2 = 0; counter2 < numout; ++counter2) { training_input >> t_vector[counter].voutput[counter2]; } } training_input.close (); //calculate division between training and test vectors numtest = int (0.8*numvectors); cout << "Training vectors: " << numtest << "; test vectors: " << (numvectors-numtest) <