openModeller  Version 1.4.0
nn.h
Go to the documentation of this file.
00001 #ifndef _LIBNN_H
00002 #define _LIBNN_H
00003 
00004 #ifdef __cplusplus
00005 extern "C" {
00006 #endif
00007 
00008 #ifndef WIN32
00009    #include <sys/time.h>
00010    #include <sys/resource.h>
00011 #else
00012    #include <time.h>
00013 #endif
00014 
00015 
00016 #include <ctype.h>
00017 #include <float.h>
00018 #include <string.h>
00019 #include <stdarg.h>
00020 
00021 
00022 struct nn_parameter
00023 {
00024   // General Variables
00025   int inp;
00026   int hid;
00027   int outp;
00028   int pattern;
00029   double learning_rate;
00030   double momentum;
00031 
00032   // Choice Variable between training by epoch or minimum error
00033   int choice;
00034 
00035   // Variables especified of training by epoch
00036   double epoch;
00037 
00038   // Variables especified of training by minimum error
00039   double minimum_error;
00040 };
00041 
00042 
00043 /*
00044  * Neural Network was based on the algorithm created by Paras Chopra. 
00045  * Email: paras1987@gmail.com
00046  * Web: www.paraschopra.com
00047  * 
00048  * Changes made in the algorithm are shown with A&F at the beginning of the sentence.
00049  * Amended by Alex Oshika Avilla & Fabricio Augusto Rodrigues
00050  */
00051 
00052 #include <stdio.h>
00053 #include <stdlib.h>
00054 #include <math.h> //For tanh
00055 
00056 
00057 /*A&F*/// returns a float in the range -1.0f -> - 1.0f
00058 #define RANDOM_CLAMP    (((double)rand()-(float)rand())/10000000)
00059 
00060 /*A&F*///returns a float between 0 & 1
00061 #define RANDOM_NUM    ((double)rand()/(10000000+1))
00062 
00063 //using namespace std;
00064 
00065 
00066 /*A&F*/class Dendrite{
00067 
00068   public:
00069 
00070     // Weights of the neuron
00071     double d_weight;
00072     double d_weight_ancient;
00073     double d_weight_actual;
00074     unsigned long d_points_to; // The index of the neuron of the next layer to which it points
00075 
00076     Dendrite(double weight = 0.0, double weight_ancient = 0.0, double weight_actual = 0.0, unsigned long points_to = 0){ //Constructor
00077 
00078   d_weight = weight;
00079   d_weight_ancient = weight_ancient;
00080   d_weight_actual = weight_actual;
00081   d_points_to = points_to; // Give it a initial value
00082     }
00083 };
00084 
00085 
00086 class Neuron{
00087 
00088   public:
00089   
00090     unsigned long n_ID; // ID of a particular neuron in a layer. Used to find a particular neuron in an array
00091     double n_value; // Value which Neuron currently is holding
00092     double n_bias;  // Bias of the neuron
00093     double n_delta; // Used in back  prop. Note it is backprop specific
00094 
00095     Dendrite *Dendrites; // Dendrites
00096 
00097     // Constructor assigning initial values
00098     Neuron(unsigned long ID = 0,double value = 0.0,double bias = 0.0){
00099 
00100   n_ID = ID;
00101   n_value = value;
00102         n_bias = bias;
00103         n_delta = 0.0;
00104     }
00105 
00106     void SetDendrites(unsigned long dendrite){ // Set the dendrites from the neuron to given dendrite
00107 
00108   Dendrites = new Dendrite[dendrite];
00109 
00110         for(unsigned long i = 0; i < dendrite; i++){
00111 
00112     Dendrites[i].d_points_to = i; // Initialize the dendrite to attach to next layer
00113         }
00114     }
00115 };
00116 
00117 
00118 class Layer{
00119 
00120   public:
00121   
00122     Neuron *Neurons; // Pointer to array of neurons
00123 
00124     /*Layer(int size = 1){    // Size is no. of neurons in it
00125 
00126   Neurons = new Neuron [size];
00127     }  */
00128 
00129     void Initialize(int size) {   // Initialize the layer
00130 
00131   Neurons = new Neuron [size];
00132     }
00133 
00134     ~Layer(){ // Destructor deletes Neurons from the memory
00135 
00136   delete Neurons;
00137     }
00138 
00139     Neuron GetNeuron(int index){  // Give the neuron at index
00140 
00141   return Neurons[index];
00142     }
00143 
00144     void SetNeuron(Neuron neuron, int index){ // Sets the neuron
00145 
00146   Neurons[index] = neuron;
00147     }
00148 };
00149 
00150 
00151 /*A&F*/class Network { // The real neural network
00152 
00153   public:
00154   
00155     double net_learning_rate; // Learning rate of network
00156     Layer *Layers; // The total layers in network
00157     int net_tot_layers; // Number of layers
00158     double *net_inputs; // Input array
00159     double *net_outputs;// Output layers
00160     int *net_layers; // Array which tells no. of neurons in each layer
00161     //double GetRand(void);
00162 
00163     double *square_error; // Mean square error of each training
00164     double *mean_square_error; // Total plus of each epoch
00165 
00166     float progress; // Percent of training
00167 
00168     Network() {
00169   // Blank Constructor
00170     }
00171 
00172 
00173     int SetData(double learning_rate, int layers[], int tot_layers) { // Function to set various parameters of the net
00174                 
00175   if (tot_layers<2) return(-1); // Return error if total no. of layers < 2
00176                                                // Because input and output layers are necessary
00177                 
00178   net_learning_rate = learning_rate;
00179 
00180         net_layers = new int [tot_layers]; // Initialize the layers array
00181 
00182         Layers = new Layer[tot_layers];
00183 
00184 
00185         for(int i = 0; i < tot_layers; i++){
00186 
00187           net_layers[i] = layers[i];
00188 
00189           Layers[i].Initialize(layers[i]); // Initialize each layer with the specified size
00190         }
00191 
00192 
00193   net_inputs = new double[layers[0]];
00194 
00195         net_outputs = new double[layers[tot_layers-1]];
00196 
00197         net_tot_layers = tot_layers;
00198 
00199 
00200         return 0;
00201     }
00202 
00203     
00204     void SetInputs(vector<double> inputs) const{ // Function to set the inputs
00205                  
00206   for(int i = 0; i < net_layers[0]; i++){
00207 
00208     Layers[0].Neurons[i].n_value = inputs[i];
00209         }
00210     }
00211 
00212 
00213     void RandomizeWB(void){ // Randomize weights and biases
00214 
00215   int i,j,k;
00216 
00217         for(i = 0; i < net_tot_layers; i++){
00218 
00219           for(j = 0; j < net_layers[i]; j++){
00220 
00221             if(i != net_tot_layers-1){ // Last layer does not require weights
00222 
00223     Layers[i].Neurons[j].SetDendrites(net_layers[i+1]); //Initialize the dendrites
00224 
00225     for(k = 0; k < net_layers[i+1]; k++){
00226 
00227       Layers[i].Neurons[j].Dendrites[k].d_weight = 0.000000; // Let weight be the zero value
00228       Layers[i].Neurons[j].Dendrites[k].d_weight_ancient = 0.000000; // Let weight be the zero value
00229       Layers[i].Neurons[j].Dendrites[k].d_weight_actual = GetRand(); // Let weight be the random value
00230           }
00231     
00232              }
00233 
00234              if(i != 0){ // First layer does not need biases
00235 
00236     Layers[i].Neurons[j].n_bias = GetRand();
00237              }
00238     }
00239   }
00240     }
00241   
00242 
00243     double * GetOutput(void) const{ // Gives the output of the net
00244     
00245   double *outputs;
00246   int i,j,k;
00247 
00248   outputs = new double[net_layers[net_tot_layers-1]]; // Temp ouput array
00249 
00250   for(i = 1; i < net_tot_layers; i++){
00251 
00252     for(j = 0; j < net_layers[i]; j++){
00253 
00254             Layers[i].Neurons[j].n_value = 0;
00255                           
00256       for(k = 0; k < net_layers[i-1]; k++){
00257 
00258     Layers[i].Neurons[j].n_value = Layers[i].Neurons[j].n_value + Layers[i-1].Neurons[k].n_value * Layers[i-1].Neurons[k].Dendrites[j].d_weight; // Multiply and add all the inputs
00259       }
00260 
00261             Layers[i].Neurons[j].n_value = Layers[i].Neurons[j].n_value + Layers[i].Neurons[j].n_bias; // Add bias
00262 
00263             Layers[i].Neurons[j].n_value = Limiter(Layers[i].Neurons[j].n_value);  // Squash that value
00264 
00265           }
00266   }
00267 
00268         for(i = 0; i < net_layers[net_tot_layers-1]; i++){
00269 
00270     outputs[i] = Layers[net_tot_layers-1].Neurons[i].n_value;
00271   }
00272 
00273   return outputs; // Return the outputs
00274     }
00275 
00276 
00277     /******************************************************************/
00278     // Used at _GetConfiguration and _SetConfiguration in the library nn_alg.cpp
00279 
00280     double getWeight(int i, int j, int k) const{ // Get weights
00281 
00282   return Layers[i].Neurons[j].Dendrites[k].d_weight;
00283     }
00284 
00285 
00286     void setWeight(int i, int j, int k, double w){ // Set weights
00287   
00288   Layers[i].Neurons[j].Dendrites[k].d_weight = w;
00289 
00290     }
00291 
00292 
00293     double getBias(int i, int j) const{ // Get bias
00294 
00295   return Layers[i].Neurons[j].n_bias;
00296     }
00297 
00298 
00299     void setBias(int i, int j, double b){ // Set bias
00300 
00301   Layers[i].Neurons[j].n_bias = b;
00302     }
00303     /******************************************************************/
00304 
00305 
00306     void Update(void){ // Just a dummy function
00307 
00308   double *temp; // Temperory pointer
00309         temp = GetOutput();
00310         //GetOutput();
00311         delete[] temp;
00312     }
00313 
00314 
00315      /*void SetOutputs(double outputs[]){ //Set the values of the output layer
00316 
00317   for(unsigned long i = 0; i < net_layers[net_tot_layers-1]; i++){
00318 
00319     Layers[net_tot_layers-1].Neurons[i].n_value = outputs[i]; //Set the value
00320         }
00321     } */
00322 
00323 
00324     double Limiter(double value) const{ // Limiet to limit value between 1 and -1
00325 
00326   //return tanh(value);   // To use tanh fuction
00327         return (1.0/(1+exp(-value))); // To use sigmoid function
00328     }
00329 
00330 
00331     double GetRand(void){  // Return a random number between range -1 e 1 using time to seed the srand function
00332 
00333   int seconds;
00334 
00335 #ifndef WIN32
00336         struct timeval time;
00337         gettimeofday( &time, (struct timezone *)NULL );
00338         seconds = (int)time.tv_usec;
00339 #else
00340         time_t timer = time( NULL );
00341         struct tm *tblock = localtime(&timer);
00342         seconds = tblock->tm_sec;
00343 #endif
00344 
00345         int seed = int(seconds + 100*RANDOM_CLAMP + 100*RANDOM_NUM);
00346         //srand(seconds);
00347         srand(seed);
00348 
00349 #ifdef _GLIBCPP_HAVE_DRAND48
00350         srand48(seed);
00351 #endif
00352 
00353         return ((RANDOM_CLAMP+RANDOM_NUM)/400);
00354    }
00355 
00356 
00357     double SigmaWeightDelta( unsigned long layer_no, unsigned long neuron_no){ // Calculate sum of weights * delta. Used in back prop. layer_no is layer number. Layer number and neuron number can be zero and neuron_no is neuron number.
00358 
00359   double result = 0.0;
00360  
00361   for(int i = 0; i < net_layers[layer_no+1]; i++) { // Go through all the neurons in the next layer
00362 
00363     result = result + Layers[layer_no].Neurons[neuron_no].Dendrites[i].d_weight * Layers[layer_no+1].Neurons[i].n_delta; // Comput the summation
00364         }
00365 
00366   return result;
00367     }
00368 
00369 
00370 /*
00371     For output layer:
00372 
00373     Delta = (TargetO - ActualO) * ActualO * (1 - ActualO)
00374     Weight = Weight + LearningRate * Delta * Input
00375 
00376     For hidden layers:
00377 
00378     Delta =  ActualO * (1-ActualO) * Summation(Weight_from_current_to_next AND Delta_of_next)
00379     Weight = Weight + LearningRate * Delta * Input
00380 */
00381 
00382 
00383     void setError(int max_pattern){ // Function to set the errors
00384 
00385   mean_square_error = new double;
00386   *mean_square_error = 0.000000;
00387   
00388   square_error = new double [max_pattern];
00389 
00390   for(int i = 0; i < max_pattern; i++){
00391 
00392     square_error[i] = 0.000000;
00393   }
00394     }
00395 
00396 
00397     void addError(int max_pattern){ // Function to add the errors
00398 
00399   for(int i = 0; i < max_pattern; i++){
00400 
00401     *mean_square_error += square_error[i];
00402   }
00403   
00404   delete[] square_error;
00405     }
00406 
00407 
00408     int Train(vector<double> inputs, vector<double> outputs, int number_pattern, int max_pattern, double momentum){ // The standard Backprop Learning algorithm
00409 
00410   int i,j,k;
00411 
00412   double *Target = new double;
00413   double *Delta = new double;
00414   double *Actual = new double;
00415   double *error = new double;;
00416 
00417 
00418         SetInputs(inputs); // Set the inputs
00419 
00420   Update(); // Update all the values
00421 
00422         //SetOutputs(outputs); // Set the outputs
00423 
00424 
00425   if(number_pattern == 0){
00426   
00427     setError(max_pattern);
00428   }
00429 
00430 
00431         for(i = (net_tot_layers-1); i > 0; i--){ // Go from last layer to first layer
00432 
00433           for(j = 0; j < net_layers[i]; j++) {// Go thru every neuron
00434 
00435             if(i == (net_tot_layers-1)){ // Output layer, Needs special atential
00436 
00437     (*Target) = outputs[j]; // Target value
00438     (*Actual) = Layers[i].Neurons[j].n_value; // Actual value
00439                            
00440     (*Delta) = ((*Target) - (*Actual)) * (*Actual) * (1 - (*Actual)); // Function to compute error
00441                            
00442     Layers[i].Neurons[j].n_delta = (*Delta); // Compute the delta
00443 
00444 
00445                 for(k = 0; k < net_layers[i-1]; k++) {
00446 
00447             Layers[i-1].Neurons[k].Dendrites[j].d_weight = ( Layers[i-1].Neurons[k].Dendrites[j].d_weight_actual) + ( net_learning_rate * (*Delta) * Layers[i-1].Neurons[k].n_value) + (momentum * ( Layers[i-1].Neurons[k].Dendrites[j].d_weight_actual - Layers[i-1].Neurons[k].Dendrites[j].d_weight_ancient)); // Calculate the new weights
00448 
00449             Layers[i-1].Neurons[k].Dendrites[j].d_weight_ancient = Layers[i-1].Neurons[k].Dendrites[j].d_weight_actual;
00450       Layers[i-1].Neurons[k].Dendrites[j].d_weight_actual = Layers[i-1].Neurons[k].Dendrites[j].d_weight; 
00451                 }
00452 
00453                 Layers[i].Neurons[j].n_bias = Layers[i].Neurons[j].n_bias + (*Delta) * net_learning_rate * 1; // n_value is always 1 for bias
00454 
00455 
00456     *error = ((*Target) - (*Actual));
00457       }
00458       else { // Here
00459                            
00460     // Target value
00461                 (*Actual) = Layers[i].Neurons[j].n_value; // Actual value
00462 
00463                 (*Delta) =  (*Actual) * (1 - (*Actual)) * SigmaWeightDelta(i,j); // Function to compute error
00464 
00465 
00466                 for(k = 0; k < net_layers[i-1]; k++) {
00467 
00468             Layers[i-1].Neurons[k].Dendrites[j].d_weight = ( Layers[i-1].Neurons[k].Dendrites[j].d_weight_actual) + ( net_learning_rate * (*Delta) * Layers[i-1].Neurons[k].n_value) + (momentum * ( Layers[i-1].Neurons[k].Dendrites[j].d_weight_actual - Layers[i-1].Neurons[k].Dendrites[j].d_weight_ancient)); // Calculate the new weights
00469 
00470             Layers[i-1].Neurons[k].Dendrites[j].d_weight_ancient = Layers[i-1].Neurons[k].Dendrites[j].d_weight_actual;
00471       Layers[i-1].Neurons[k].Dendrites[j].d_weight_actual = Layers[i-1].Neurons[k].Dendrites[j].d_weight; 
00472                 }
00473 
00474 
00475     if(i != 0){ // Input layer does not have a bias
00476 
00477       Layers[i].Neurons[j].n_bias = Layers[i].Neurons[j].n_bias + (*Delta) * net_learning_rate * 1; // n_value is always 1 for bias
00478     }
00479       }
00480     }
00481   }
00482 
00483 
00484   square_error[number_pattern] = (*error) * (*error); 
00485 
00486 
00487   if(number_pattern == (max_pattern - 1)){
00488 
00489     addError(max_pattern);
00490   }
00491 
00492 
00493   delete Target;
00494   delete Actual;
00495   delete Delta;
00496   delete error;
00497 
00498 
00499   return 0;
00500     }
00501 
00502 
00503     // Used to training by epoch
00504     void trainingEpoch( unsigned long actual_epoch, double epoch_total, int patterns){
00505 
00506   *mean_square_error = sqrt(*mean_square_error/patterns);
00507 
00508 
00509   progress = (float)(1.0-(epoch_total - (actual_epoch+1.0))/(epoch_total));
00510 
00511   delete mean_square_error;
00512     }
00513 
00514 
00515     // Used to training by minimum error
00516     int trainingMinimumError( int patterns, double min_error){
00517 
00518   int converg = 0;
00519 
00520   *mean_square_error = sqrt(*mean_square_error/patterns);
00521 
00522   
00523   if(*mean_square_error < min_error){
00524 
00525     converg = 1;
00526     progress = 1;
00527   }
00528 
00529   else{
00530 
00531     progress = (float)(1.0-(*mean_square_error - min_error)/(*mean_square_error));
00532   }
00533 
00534 
00535   delete mean_square_error;
00536 
00537   return converg;
00538     }
00539 
00540 
00541     // Percent of training
00542     float getProgress(){
00543 
00544   return progress;
00545     }
00546 
00547 
00548 
00549     ~Network(){ }//delete Layers; }
00550 
00551 };
00552 
00553 
00554 #ifdef __cplusplus
00555 }
00556 #endif
00557 
00558 #endif /* _LIBNN_H */