/////////////////////////////////////////////////////////////// // // // proto1.cpp - prototype for back-propogation neural net // // // // version: 1.0 // // Language: Visual C++, ver 6.0 // // Platform: Micron Dual Pentium Pro 200 // // Windows NT 4.0, service pack 3 // // Application: ELE591/791 Example // // Author: Jim Fawcett // // CST 2-187, (315) 443-3948 // // fawcett@ecs.syr.edu // // // /////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include "bneuron.h" //----< output desired for NNet >------------------------------ double desired(double time) { if(time < -1.0) return -1.0; if(time < 1.0) return time; return 1.0; } //----< randomize time >--------------------------------------- double randomize(double min, double max, bool newSeed) { static int count = 654321; static bool beenHere = false; double scaleFactor = (max-min)/RAND_MAX; if(newSeed || !beenHere) { count += 123456; srand((unsigned)time(NULL) + count); beenHere = true; } return rand()*scaleFactor + min; } // //----< compute NNet output >---------------------------------- double NNoutput(double input, sneuron hiddenLayer[], lneuron outputLayer[]) { hiddenLayer[0].input(0) = 1.0; // bias hiddenLayer[0].input(1) = input; double hiddenOut = hiddenLayer[0].output(); outputLayer[0].input(0) = 1.0; // bias outputLayer[0].input(1) = hiddenOut; return outputLayer[0].output(); } //----< update weights with back-propogation algorithm >------- void backProp(double error, sneuron hiddenLayer[], lneuron outputLayer[]) { double eta = 0.25; // output layer double slope = 1.0; double epsOut = -2.0*error*slope; outputLayer[0].weight(0) += -eta*epsOut*outputLayer[0].input(0); outputLayer[0].weight(1) += -eta*epsOut*outputLayer[0].input(1); // hidden layer slope = hiddenLayer[0].output()*(1.0 - hiddenLayer[0].output()); double epsHid = slope*epsOut*outputLayer[0].weight(1); hiddenLayer[0].weight(0) += -eta*epsHid*hiddenLayer[0].input(0); hiddenLayer[0].weight(1) += -eta*epsHid*hiddenLayer[0].input(1); } // //----< build NNet and run it >-------------------------------- void main() { sneuron hiddenLayer[1] = { sneuron(2) }; lneuron outputLayer[1] = { lneuron(2) }; hiddenLayer[0].randWts(-0.2,0.2,true); outputLayer[0].randWts(-0.2,0.2,true); cout << "\n Training 1:1:1 backpropagation network " << "\n ========================================\n\n"; ofstream log("wts.dat"); // outer loop repeats until network error // fractional change is very small double error, sumPrev = 1000, fractionalChange; do { int count = 0; double sum = 0; // inner loop computes smoothed absolute error // over 20 cycles to test for convergence do { double time = randomize(-2.0, 2.0, true); double output = NNoutput(time,hiddenLayer,outputLayer); error = desired(time) - output; sum += fabs(error); backProp(error,hiddenLayer,outputLayer); log << setw(12) << hiddenLayer[0].weight(0) << ',' << setw(12) << hiddenLayer[0].weight(1) << ',' << setw(12) << outputLayer[0].weight(0) << ',' << setw(12) << outputLayer[0].weight(1) << endl; } while(count++ < 20); fractionalChange = (sumPrev - sum)/sumPrev; sumPrev = sum; cout << " error sum = " << sum << endl; } while(fractionalChange > 0.0001); log.close(); cout << "\n Testing 1:1:1 backpropagation network " << "\n =======================================\n\n"; ofstream out("test.dat"); cout << setw(17) << "desired output" << setw(17) << "network output" << endl; double time; for(time = -2.0; time < +2.0; time += 0.1) { double output = NNoutput(time,hiddenLayer,outputLayer); cout << setw(17) << desired(time) << setw(17) << output << '\n'; out << setw(15) << desired(time) << ',' << setw(15) << output << '\n'; } out.close(); cout << endl; }