home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 618a.lha / NeuralNetwork / neural_network.cc < prev    next >
C/C++ Source or Header  |  1992-03-01  |  24KB  |  810 lines

  1.  
  2. #include <stdio.h>
  3. #include <new.h>
  4. #include <math.h>
  5. #include <File.h>
  6. #include "Neural_network.h"
  7.  
  8. void Neural_network::allocate_matrices ()
  9. {
  10.  
  11.   // Time to allocate the entire neural_net structure
  12.   // Activation matrices
  13.   hidden1_act = new double [num_hidden1];
  14.   hidden2_act = new double [num_hidden2];
  15.   output_act = new double [num_outputs];
  16.  
  17.   // Weight matrices
  18.   input_weights = new double [num_hidden1 * num_inputs];
  19.   hidden1_weights = new double [num_hidden2 * num_hidden1];
  20.   hidden2_weights = new double [num_outputs * num_hidden2];
  21.  
  22.   // Learning rate matrices for each weight's learning rate.
  23.   // Needed for delta-bar-delta algorithm
  24.   input_learning_rate = new double [num_hidden1 * num_inputs];
  25.   hidden1_learning_rate = new double [num_hidden2 * num_hidden1];
  26.   hidden2_learning_rate = new double [num_outputs * num_hidden2];
  27.  
  28.   // Learning rate deltas for each weight's learning rate.
  29.   // Needed for delta-bar-delta algorithm.
  30.   input_learning_delta = new double [num_hidden1 * num_inputs];
  31.   hidden1_learning_delta = new double [num_hidden2 * num_hidden1];
  32.   hidden2_learning_delta = new double [num_outputs * num_hidden2];
  33.  
  34.   // Delta bar matrices for each weight's delta bar.
  35.   // Needed for delta-bar-delta algorithm.
  36.   input_learning_delta_bar = new double [num_hidden1 * num_inputs];
  37.   hidden1_learning_delta_bar = new double [num_hidden2 * num_hidden1];
  38.   hidden2_learning_delta_bar = new double [num_outputs * num_hidden2];
  39.  
  40.   // Weight delta matrices for each weights delta.
  41.   // Needed for BackPropagation algorithm.
  42.   input_weights_sum_delta = new double [num_hidden1 * num_inputs];
  43.   hidden1_weights_sum_delta = new double [num_hidden2 * num_hidden1];
  44.   hidden2_weights_sum_delta = new double [num_outputs * num_hidden2];
  45.  
  46.   // Sum of delta * weight matrices for each weight.
  47.   // Needed for BackPropagation algorithm.
  48.   hidden1_sum_delta_weight = new double [num_hidden2 * num_hidden1];
  49.   hidden2_sum_delta_weight = new double [num_outputs * num_hidden2];
  50.  
  51.   /* Done neural net allocation */
  52. }
  53.  
  54. void Neural_network::initialize_matrices (double range)
  55. {
  56.   int    x,y;
  57.   double rand_max;
  58.  
  59.   training_examples = 0;
  60.   examples_since_update = 0;
  61.  
  62.   rand_max = RAND_MAX;
  63.   /* Initialize all weights from -range to +range randomly */
  64.   for (x = 0; x < num_hidden1; ++x)
  65.     {
  66.       hidden1_sum_delta_weight [x] = 0.0;
  67.  
  68.       for (y = 0; y < num_inputs; ++y)
  69.         {
  70.           input_weights [x * num_inputs + y] = rand () / rand_max * range;
  71.           if ( rand () < (RAND_MAX / 2) )
  72.               input_weights [x * num_inputs + y] *= -1.0;
  73.  
  74.           input_weights_sum_delta [x * num_inputs + y] = 0.0;
  75.           input_learning_rate [x * num_inputs + y] = learning_rate;
  76.           input_learning_delta [x * num_inputs + y] = 0.0;
  77.           input_learning_delta_bar [x * num_inputs + y] = 0.0;
  78.         }
  79.     }
  80.  
  81.   for (x = 0; x < num_hidden2; ++x)
  82.     {
  83.       hidden2_sum_delta_weight [x] = 0.0;
  84.  
  85.       for (y = 0; y < num_hidden1; ++y)
  86.         {
  87.           hidden1_weights [x * num_hidden1 + y] = rand () / rand_max * range;
  88.           if ( rand () < (RAND_MAX / 2) )
  89.               hidden1_weights [x * num_hidden1 + y] *= -1.0;
  90.  
  91.           hidden1_weights_sum_delta [x * num_hidden1 + y] = 0.0;
  92.           hidden1_learning_rate [x * num_hidden1 + y] = learning_rate;
  93.           hidden1_learning_delta [x * num_hidden1 + y] = 0.0;
  94.           hidden1_learning_delta_bar [x * num_hidden1 + y] = 0.0;
  95.         }
  96.     }
  97.  
  98.   for (x = 0; x < num_outputs; ++x)
  99.     {
  100.       for (y = 0; y < num_hidden2; ++y)
  101.         {
  102.           hidden2_weights [x * num_hidden2 + y] = rand () / rand_max * range;
  103.           if ( rand () < (RAND_MAX / 2) )
  104.               hidden2_weights [x * num_hidden2 + y] *= -1.0;
  105.  
  106.           hidden2_weights_sum_delta [x * num_hidden2 + y] = 0.0;
  107.           hidden2_learning_rate [x * num_hidden2 + y] = learning_rate;
  108.           hidden2_learning_delta [x * num_hidden2 + y] = 0.0;
  109.           hidden2_learning_delta_bar [x * num_hidden2 + y] = 0.0;
  110.         }
  111.     }
  112.  
  113. }
  114.  
  115. void Neural_network::deallocate_matrices ()
  116. {
  117.  
  118.   // Time to destroy the entire neural_net structure
  119.   // Activation matrices
  120.   delete hidden1_act;
  121.   delete hidden2_act;
  122.   delete output_act;
  123.  
  124.   // Weight matrices
  125.   delete input_weights;
  126.   delete hidden1_weights;
  127.   delete hidden2_weights;
  128.  
  129.   // Learning rate matrices for each weight's learning rate.
  130.   // Needed for delta-bar-delta algorithm
  131.   delete input_learning_rate;
  132.   delete hidden1_learning_rate;
  133.   delete hidden2_learning_rate;
  134.  
  135.   // Learning rate deltas for each weight's learning rate.
  136.   // Needed for delta-bar-delta algorithm.
  137.   delete input_learning_delta;
  138.   delete hidden1_learning_delta;
  139.   delete hidden2_learning_delta;
  140.  
  141.   // Delta bar matrices for each weight's delta bar.
  142.   // Needed for delta-bar-delta algorithm.
  143.   delete input_learning_delta_bar;
  144.   delete hidden1_learning_delta_bar;
  145.   delete hidden2_learning_delta_bar;
  146.  
  147.   // Weight delta matrices for each weights delta.
  148.   // Needed for BackPropagation algorithm.
  149.   delete input_weights_sum_delta;
  150.   delete hidden1_weights_sum_delta;
  151.   delete hidden2_weights_sum_delta;
  152.  
  153.   // Sum of delta * weight matrices for each weight.
  154.   // Needed for BackPropagation algorithm.
  155.   delete hidden1_sum_delta_weight;
  156.   delete hidden2_sum_delta_weight;
  157.  
  158.   /* Done neural net deallocation */
  159. }
  160.  
  161. Neural_network::Neural_network (int number_inputs, int number_hidden1,
  162.                                 int number_hidden2, int number_outputs,
  163.                                 double t_epsilon, double t_skip_epsilon,
  164.                                 double t_learning_rate, double t_theta,
  165.                                 double t_phi, double t_K, double range) :
  166.                 num_inputs (number_inputs), num_hidden1 (number_hidden1),
  167.                 num_hidden2 (number_hidden2), num_outputs (number_outputs),
  168.                 epsilon (t_epsilon), skip_epsilon (t_skip_epsilon),
  169.                 learning_rate (t_learning_rate), theta (t_theta), phi (t_phi),
  170.                 K (t_K), training_examples (0), examples_since_update (0)
  171. {
  172.   allocate_matrices ();
  173.   initialize_matrices (range);
  174. }
  175.  
  176.  
  177. Neural_network::Neural_network (char *filename, int& file_error,
  178.                                 double t_epsilon, double t_skip_epsilon,
  179.                                 double t_learning_rate, double t_theta,
  180.                                 double t_phi, double t_K) :
  181.                 epsilon (t_epsilon), skip_epsilon (t_skip_epsilon),
  182.                 learning_rate (t_learning_rate), theta (t_theta), phi (t_phi),
  183.                 K (t_K), examples_since_update (0),
  184.                 hidden1_act (0), hidden2_act (0), output_act (0),
  185.                 input_weights (0), hidden1_weights (0), hidden2_weights (0),
  186.                 input_learning_rate (0), hidden1_learning_rate (0),
  187.                 hidden2_learning_rate (0), input_learning_delta (0),
  188.                 hidden1_learning_delta (0), hidden2_learning_delta (0),
  189.                 input_learning_delta_bar (0), hidden1_learning_delta_bar (0),
  190.                 hidden2_learning_delta_bar (0), input_weights_sum_delta (0),
  191.                 hidden1_weights_sum_delta (0), hidden2_weights_sum_delta (0),
  192.                 hidden1_sum_delta_weight (0), hidden2_sum_delta_weight (0)
  193. {
  194.   file_error = read_weights (filename);
  195. }
  196.  
  197. int Neural_network::read_weights (char *filename)
  198. {
  199.   File    *fp;
  200.   int     x;
  201.   long    iter;
  202.  
  203.   if ( ((fp = new File (filename,"rt")) == NULL) ||
  204.        (!fp->is_open ()) )
  205.     {
  206.       printf ("Could not read weights from file '%s'\n",filename);
  207.       return (-1);
  208.     }
  209.  
  210.   /* First read in how many iterations have been performed so far */
  211.   fp->scan ("%ld",&iter);
  212.   printf ("Iterations = %ld\n",iter);
  213.  
  214.   /* Next read in how many input nodes, hidden1 nodes, hidden2 nodes */
  215.   /* and output nodes. */
  216.   fp->scan ("%d%d%d%d",&num_inputs,&num_hidden1,&num_hidden2,&num_outputs);
  217.  
  218.   // Deallocate previous matrices
  219.   deallocate_matrices ();
  220.  
  221.   /* Allocate new matrices with new size */
  222.   allocate_matrices ();
  223.  
  224.   // Initialize all matrices and variables
  225.   initialize_matrices (1.0);
  226.   training_examples = iter;
  227.  
  228.   /* Read input->hidden1 weights from file. */
  229.   for (x = 0; x < num_inputs * num_hidden1; ++x)
  230.     {
  231.       fp->scan ("%lf",&input_weights [x]);
  232.     }
  233.  
  234.   /* Read hidden1->hidden2 weights from file. */
  235.   for (x = 0; x < num_hidden1 * num_hidden2; ++x)
  236.     {
  237.       fp->scan ("%lf",&hidden1_weights [x]);
  238.     }
  239.  
  240.   /* Read hidden2->output weights from file. */
  241.   for (x = 0; x < (num_hidden2 * num_outputs); ++x)
  242.     {
  243.       fp->scan ("%lf",&hidden2_weights [x]);
  244.     }
  245.  
  246.   /* Now all the weights have been loaded */
  247.  delete fp;
  248.  
  249.  return (0);
  250. }
  251.  
  252.  
  253.  
  254. int Neural_network::save_weights (char *filename)
  255. {
  256.   File *fp;
  257.   int   x;
  258.  
  259.   if ( ((fp = new File (filename,"wt")) == NULL) ||
  260.        (!fp->is_open ()) )
  261.     {
  262.       printf ("Could not save weights to file '%s'\n",filename);
  263.       return (-1);
  264.     }
  265.  
  266.   /* First write out how many iterations have been performed so far */
  267.   fp->form (" %ld\n",training_examples);
  268.  
  269.   /* Next write out how many input nodes, hidden1 nodes, hidden2 nodes */
  270.   /* and output nodes. */
  271.   fp->form (" %d %d %d %d\n",num_inputs,num_hidden1,num_hidden2,num_outputs);
  272.  
  273.   /* Write input->hidden1 weights to output. */
  274.   for (x = 0; x < num_inputs * num_hidden1; ++x)
  275.     {
  276.       fp->form ("%10.5f ",input_weights [x]);
  277.       if ( (x % 5) == 4 )
  278.           fp->form ("\n");
  279.     }
  280.   fp->form ("\n\n");
  281.  
  282.   /* Write hidden1->hidden2 weights to output. */
  283.   for (x = 0; x < num_hidden1 * num_hidden2; ++x)
  284.     {
  285.       fp->form ("%10.5f ",hidden1_weights [x]);
  286.       if ( (x % 5) == 4 )
  287.           fp->form ("\n");
  288.     }
  289.   fp->form ("\n\n");
  290.  
  291.   /* Write hidden2->output weights to output. */
  292.   for (x = 0; x < (num_hidden2 * num_outputs); ++x)
  293.     {
  294.       fp->form ("%10.5f ",hidden2_weights [x]);
  295.       if ( (x % 5) == 4 )
  296.           fp->form ("\n");
  297.     }
  298.   fp->form ("\n\n");
  299.  
  300.   fp->flush ();
  301.   printf ("Flushed file\n");
  302.   fp->close ();
  303.   printf ("Closed file\n");
  304.  
  305.   delete fp;
  306.  
  307.   /* Now all the weights have been saved */
  308.   return (0);
  309. }
  310.  
  311.  
  312.  
  313. void Neural_network::set_size_parameters (int number_inputs,
  314.                                  int number_hidden1, int number_hidden2,
  315.                                  int number_outputs, double range)
  316. {
  317.   double *new_input_weights,*new_hidden1_weights,*new_hidden2_weights;
  318.   double rand_max;
  319.   int    x;
  320.  
  321.   rand_max = RAND_MAX;
  322.  
  323.   // Allocate new weight matrices with new size
  324.   new_input_weights = new double [number_hidden1 * number_inputs];
  325.   new_hidden1_weights = new double [number_hidden2 * number_hidden1];
  326.   new_hidden2_weights = new double [number_outputs * number_hidden2];
  327.  
  328.   // Copy over all weights
  329.   // Input weights
  330.   for (x = 0; x < number_hidden1 * number_inputs; ++x)
  331.     {
  332.       // IF the new size is larger than the old size, THEN make new connections
  333.       // a random weight between +-range.
  334.       if ( x >= (num_hidden1 * num_inputs) )
  335.         {
  336.           new_input_weights [x] = rand () / rand_max * range;
  337.           if ( rand () < (RAND_MAX / 2) )
  338.               new_input_weights [x] *= -1.0;
  339.         }
  340.       else
  341.           new_input_weights [x] = input_weights [x];
  342.     }
  343.  
  344.   // Hidden1 weights
  345.   for (x = 0; x < number_hidden2 * number_hidden1; ++x)
  346.     {
  347.       // IF the new size is larger than the old size, THEN make new connections
  348.       // a random weight between +-range.
  349.       if ( x >= (num_hidden2 * num_hidden1) )
  350.         {
  351.           new_hidden1_weights [x] = rand () / rand_max * range;
  352.           if ( rand () < (RAND_MAX / 2) )
  353.               new_hidden1_weights [x] *= -1.0;
  354.         }
  355.       else
  356.           new_hidden1_weights [x] = hidden1_weights [x];
  357.     }
  358.  
  359.   // Hidden2 weights
  360.   for (x = 0; x < number_outputs * number_hidden2; ++x)
  361.     {
  362.       // IF the new size is larger than the old size, THEN make new connections
  363.       // a random weight between +-range.
  364.       if ( x >= (num_outputs * num_hidden2) )
  365.         {
  366.           new_hidden2_weights [x] = rand () / rand_max * range;
  367.           if ( rand () < (RAND_MAX / 2) )
  368.               new_hidden2_weights [x] *= -1.0;
  369.         }
  370.       else
  371.           new_hidden2_weights [x] = hidden2_weights [x];
  372.     }
  373.  
  374.   // All weights have been copied.
  375.  
  376.   // Change size paramters
  377.   num_inputs = number_inputs;
  378.   num_hidden1 = number_hidden1;
  379.   num_hidden2 = number_hidden2;
  380.   num_outputs = number_outputs;
  381.  
  382.   // Deallocate all matrices
  383.   deallocate_matrices ();
  384.  
  385.   // Allocate new nerual network matrices with the correct size and initialize
  386.   allocate_matrices ();
  387.   initialize_matrices (1.0);
  388.  
  389.   // Now deallocate new randomly initialized weight matrices and assign them
  390.   // to the new weight matrices that have the correct weight values.
  391.   delete input_weights;
  392.   delete hidden1_weights;
  393.   delete hidden2_weights;
  394.  
  395.   input_weights = new_input_weights;
  396.   hidden1_weights = new_hidden1_weights;
  397.   hidden2_weights = new_hidden2_weights;
  398.  
  399. }
  400.  
  401.  
  402. void Neural_network::back_propagation (double input [],
  403.                                        double desired_output [],
  404.                                        int& done)
  405. {
  406.   int     x,y;
  407.   int     size;
  408.   double  delta,sum_delta,*weight,*p_sum_delta,*p_learning_delta;
  409.  
  410.   /* First check if training complete. */
  411.   for (x = num_outputs - 1; x >= 0; --x)
  412.     {
  413.       if ( fabs (desired_output [x] - output_act [x]) > epsilon )
  414.         {
  415.           done = 0;
  416.         }
  417.     }
  418.  
  419.   /* Go backward through list for speed */
  420.   size = num_hidden2;
  421.   /* First calculate deltas of weights from output to hidden layer 2. */
  422.   for (x = num_outputs - 1; x >= 0; --x)
  423.     {
  424.       weight = &hidden2_weights [x * size];
  425.       p_sum_delta = &hidden2_weights_sum_delta [x * size];
  426.       p_learning_delta = &hidden2_learning_delta [x * size];
  427.       for (y = num_hidden2 - 1; y >= 0; --y)
  428.         {
  429.           /* Formula delta = (desired - actual) * derivative
  430.              derivative = S(1 - S)
  431.              Also calculate sum of deltas * weight for next layer.
  432.           */
  433.           delta = (desired_output [x] - output_act [x])
  434.                    * SLOPE * output_act [x] * (1.0 - output_act [x]);
  435.  
  436.           hidden2_sum_delta_weight [y] += delta * weight [y];
  437.  
  438.           p_learning_delta [y] += delta;
  439.  
  440.           /* Now multiply by activation and sum in weights sum delta */
  441.           p_sum_delta [y] += delta * hidden2_act [y];
  442.         }
  443.     }
  444.  
  445.  
  446.   /* Next calculate deltas of weights between hidden layer2 and hidden
  447.      layer 1 */
  448.   size = num_hidden1;
  449.   for (x = num_hidden2 - 1; x >= 0; --x)
  450.     {
  451.       sum_delta = hidden2_sum_delta_weight [x];
  452.       weight = &hidden1_weights [x * size];
  453.       p_sum_delta = &hidden1_weights_sum_delta [x * size];
  454.       p_learning_delta = &hidden1_learning_delta [x * size];
  455.       for (y = num_hidden1 - 1; y >= 0; --y)
  456.         {
  457.           /* Formula delta = SUM (previous deltas*weight)
  458.                              * derivative
  459.              previous deltas already muliplied by weight.
  460.              derivative = S(1 - S)
  461.  
  462.              Also calculate sum of deltas * weight to save from doing
  463.              it for next layer.
  464.           */
  465.  
  466.           delta = sum_delta * hidden2_act [x] *
  467.                   (1.0 - hidden2_act [x]) * SLOPE;
  468.  
  469.           hidden1_sum_delta_weight [y] += delta * weight [y];
  470.  
  471.           p_learning_delta [y] += delta;
  472.  
  473.           /* Now multiply by activation and sum in weights_sum_delta */
  474.           p_sum_delta [y] += delta * hidden1_act [y];
  475.         }
  476.       hidden2_sum_delta_weight [x] = 0.0;
  477.     }
  478.  
  479.   /* Finally calculate deltas of weights between hidden layer 1 and input
  480.      layer */
  481.   size = num_inputs;
  482.   for (x = num_hidden1 - 1; x >= 0; --x)
  483.     {
  484.       sum_delta = hidden1_sum_delta_weight [x];
  485.       p_sum_delta = &input_weights_sum_delta [x * size];
  486.       p_learning_delta = &input_learning_delta [x * size];
  487.       for (y = num_inputs - 1; y >= 0; --y)
  488.         {
  489.           /* Formula delta = SUM (previous deltas*weight)
  490.                              * derivative * activation of input
  491.              previous deltas already muliplied by weight
  492.              derivative = S(1 - S)
  493.           */
  494.           delta = sum_delta * hidden1_act [x] *
  495.                   (1.0 - hidden1_act [x]) * SLOPE;
  496.  
  497.           p_learning_delta [y] += delta;
  498.  
  499.           p_sum_delta [y] += (delta * input [y]);
  500.         }
  501.       hidden1_sum_delta_weight [x] = 0.0;
  502.     }
  503.  
  504.   /* Now all deltas have been calculated and added into their appropriate
  505.      neuron connection. */
  506.   ++examples_since_update;
  507.  
  508. }
  509.  
  510.  
  511. double Neural_network::calc_forward (double input [], double desired_output [],
  512.                                      int& num_wrong, int& skip, int print_it,
  513.                                      int& actual_printed)
  514. {
  515.   int     x,y,wrong;
  516.   int     size;
  517.   double  *weight,error,abs_error;
  518.  
  519.   skip = 1;
  520.   wrong = 0;
  521.   error = 0.0;
  522.  
  523.   /* Go backward for faster processing */
  524.   /* Calculate hidden layer 1's activation */
  525.   size = num_inputs;
  526.   for (x = num_hidden1 - 1; x >= 0;  --x)
  527.     {
  528.       hidden1_act [x] = 0.0;
  529.       weight = &input_weights [x * size];
  530.       for (y = num_inputs - 1; y >= 0; --y)
  531.         {
  532.           hidden1_act [x] += (input [y] * weight [y]);
  533.         }
  534.       hidden1_act [x] = S(hidden1_act [x]);
  535.     }
  536.  
  537.   /* Calculate hidden layer 2's activation */
  538.   size = num_hidden1;
  539.   for (x = num_hidden2 - 1; x >= 0; --x)
  540.     {
  541.       hidden2_act [x] = 0.0;
  542.       weight = &hidden1_weights [x * size];
  543.       for (y = num_hidden1 - 1; y >= 0; --y)
  544.         {
  545.           hidden2_act [x] += (hidden1_act [y] * weight [y]);
  546.         }
  547.       hidden2_act [x] = S(hidden2_act [x]);
  548.     }
  549.  
  550.   /* Calculate output layer's activation */
  551.   size = num_hidden2;
  552.   for (x = num_outputs - 1; x >= 0; --x)
  553.     {
  554.       output_act [x] = 0.0;
  555.       weight = &hidden2_weights [x * size];
  556.       for (y = num_hidden2 - 1; y >= 0; --y)
  557.         {
  558.           output_act [x] += hidden2_act [y] * weight [y];
  559.         }
  560.       output_act [x] = S(output_act [x]);
  561.       abs_error = fabs (output_act [x] - desired_output [x]);
  562.       error += abs_error;
  563.       if ( abs_error > epsilon )
  564.           wrong = 1;
  565.       if ( abs_error > skip_epsilon )
  566.           skip = 0;
  567.     }
  568.  
  569.   if ( wrong )
  570.       ++num_wrong;
  571.  
  572.   if ( print_it == 2 )
  573.     {
  574.       for (x = 0; x < num_outputs; ++x)
  575.         {
  576.           printf ("%6.4f ",output_act [x]);
  577.         }
  578.       ++actual_printed;
  579.     }
  580.   else if ( print_it && wrong )
  581.     {
  582.       for (x = 0; x < num_outputs; ++x)
  583.         {
  584.           printf ("%6.4f ",fabs (desired_output [x] - output_act [x]));
  585.         }
  586.       ++actual_printed;
  587.     }
  588.  
  589.   return (error);
  590.  
  591. }
  592.  
  593.  
  594. void Neural_network::update_weights ()
  595. {
  596.   int     x,y;
  597.   int     size;
  598.   double  rate,*p_ldelta,*p_ldelta_bar,*weight,*p_lrate,*p_sum_delta;
  599.  
  600.   // Check to see if any changes have been calculated.
  601.   if ( examples_since_update == 0 )
  602.     {
  603.       return;
  604.     }
  605.  
  606.   /* Go backward for slightly faster processing */
  607.   /* First add deltas of weights from output to hidden layer 2. */
  608.   size = num_hidden2;
  609.   for (x = num_outputs - 1; x >= 0; --x)
  610.     {
  611.       p_ldelta = &hidden2_learning_delta [x * size];
  612.       p_ldelta_bar = &hidden2_learning_delta_bar [x * size];
  613.       weight = &hidden2_weights [x * size];
  614.       p_lrate = &hidden2_learning_rate [x * size];
  615.       p_sum_delta = &hidden2_weights_sum_delta [x * size];
  616.  
  617.       for (y = num_hidden2 - 1; y >= 0; --y)
  618.         {
  619.           rate = p_ldelta [y] * p_ldelta_bar [y];
  620.           if ( rate < 0.0 )
  621.             {
  622.               p_lrate [y] -= (phi * p_lrate [y]);
  623.             }
  624.           else if ( rate > 0.0 )
  625.             {
  626.               p_lrate [y] += K;
  627.             }
  628.  
  629.           weight [y] += (p_lrate [y] * p_sum_delta [y]);
  630.           p_sum_delta [y] = 0.0;
  631.           p_ldelta_bar [y] *= theta;
  632.           p_ldelta_bar [y] += ((1.0 - theta) * p_ldelta [y]);
  633.           p_ldelta [y] = 0.0;
  634.         }
  635.     }
  636.  
  637.   /* Next add deltas of weights between hidden layer2 and hidden
  638.      layer 1 */
  639.   size = num_hidden1;
  640.   for (x = num_hidden2 - 1; x >= 0; --x)
  641.     {
  642.       p_ldelta = &hidden1_learning_delta [x * size];
  643.       p_ldelta_bar = &hidden1_learning_delta_bar [x * size];
  644.       weight = &hidden1_weights [x * size];
  645.       p_lrate = &hidden1_learning_rate [x * size];
  646.       p_sum_delta = &hidden1_weights_sum_delta [x * size];
  647.  
  648.       for (y = num_hidden1 - 1; y >= 0; --y)
  649.         {
  650.           rate = p_ldelta [y] * p_ldelta_bar [y];
  651.           if ( rate < 0.0 )
  652.             {
  653.               p_lrate [y] -= (phi * p_lrate [y]);
  654.             }
  655.           else if ( rate > 0.0 )
  656.             {
  657.               p_lrate [y] += K;
  658.             }
  659.  
  660.           weight [y] += (p_lrate [y] * p_sum_delta [y]);
  661.           p_sum_delta [y] = 0.0;
  662.           p_ldelta_bar [y] *= theta;
  663.           p_ldelta_bar [y] += ((1.0 - theta) * p_ldelta [y]);
  664.           p_ldelta [y] = 0.0;
  665.         }
  666.     }
  667.  
  668.   /* Finally add deltas of weights between hidden layer 1 and input
  669.      layer */
  670.   size = num_inputs;
  671.   for (x = num_hidden1 - 1; x >= 0; --x)
  672.     {
  673.       p_ldelta = &input_learning_delta [x * size];
  674.       p_ldelta_bar = &input_learning_delta_bar [x * size];
  675.       weight = &input_weights [x * size];
  676.       p_lrate = &input_learning_rate [x * size];
  677.       p_sum_delta = &input_weights_sum_delta [x * size];
  678.  
  679.       for (y = num_inputs - 1; y >= 0; --y)
  680.         {
  681.           rate = p_ldelta [y] * p_ldelta_bar [y];
  682.           if ( rate < 0.0 )
  683.             {
  684.               p_lrate [y] -= (phi * p_lrate [y]);
  685.             }
  686.           else if ( rate > 0.0 )
  687.             {
  688.               p_lrate [y] += K;
  689.             }
  690.  
  691.           weight [y] += (p_lrate [y] * p_sum_delta [y]);
  692.           p_sum_delta [y] = 0.0;
  693.           p_ldelta_bar [y] *= theta;
  694.           p_ldelta_bar [y] += ((1.0 - theta) * p_ldelta [y]);
  695.           p_ldelta [y] = 0.0;
  696.         }
  697.     }
  698.  
  699.   /* Now all deltas have been added into their appropriate neuron
  700.      connection. */
  701.   training_examples += examples_since_update;
  702.   examples_since_update = 0;
  703.  
  704. }
  705.  
  706.  
  707. int Neural_network::calc_forward_test (double input [],
  708.                                        double desired_output [],
  709.                                        int print_it, double correct_eps,
  710.                                        double good_eps)
  711. {
  712.   int x,y,wrong,good;
  713.  
  714.   wrong = 0;
  715.   good = 0;
  716.  
  717.   /* Go backward for faster processing */
  718.   /* Calculate hidden layer 1's activation */
  719.   for (x = num_hidden1 - 1; x >= 0;  --x)
  720.     {
  721.       hidden1_act [x] = 0.0;
  722.       for (y = num_inputs - 1; y >= 0; --y)
  723.         {
  724.           hidden1_act [x] += (input [y] *
  725.                               input_weights [x * num_inputs + y]);
  726.         }
  727.       hidden1_act [x] = S(hidden1_act [x]);
  728.     }
  729.  
  730.   /* Calculate hidden layer 2's activation */
  731.   for (x = num_hidden2 - 1; x >= 0; --x)
  732.     {
  733.       hidden2_act [x] = 0.0;
  734.       for (y = num_hidden1 - 1; y >= 0; --y)
  735.         {
  736.           hidden2_act [x] += (hidden1_act [y] *
  737.                                  hidden1_weights [x*num_hidden1 + y]);
  738.         }
  739.       hidden2_act [x] = S(hidden2_act [x]);
  740.     }
  741.  
  742.   /* Calculate output layer's activation */
  743.   for (x = num_outputs - 1; x >= 0; --x)
  744.     {
  745.       output_act [x] = 0.0;
  746.       for (y = num_hidden2 - 1; y >= 0; --y)
  747.         {
  748.           output_act [x] += hidden2_act [y] *
  749.                                 hidden2_weights [x * num_hidden2 + y];
  750.         }
  751.       output_act [x] = S(output_act [x]);
  752.  
  753.       if ( fabs (output_act [x] - desired_output [x]) > good_eps )
  754.           wrong = 1;
  755.       else if ( fabs (output_act [x] - desired_output [x]) > correct_eps )
  756.           good = 1;
  757.     }
  758.  
  759.   if ( print_it )
  760.     {
  761.       for (x = 0; x < num_outputs; ++x)
  762.         {
  763.           printf ("%6.4f ",output_act [x]);
  764.         }
  765.     }
  766.  
  767.   if ( wrong )
  768.       return (WRONG);
  769.   else if ( good )
  770.       return (GOOD);
  771.   else
  772.       return (CORRECT);
  773. }
  774.  
  775.  
  776. void Neural_network::kick_weights (double range)
  777. {
  778.   int    x;
  779.   double rand_max;
  780.   double variation;
  781.  
  782.   rand_max = RAND_MAX;
  783.   /* Add from -range to +range to all weights randomly */
  784.   for (x = 0; x < (num_hidden1 * num_inputs); ++x)
  785.     {
  786.       variation = rand () / rand_max * range;
  787.       if ( rand () < (RAND_MAX / 2) )
  788.           variation *= -1.0;
  789.       input_weights [x] += variation;
  790.     }
  791.  
  792.   for (x = 0; x < (num_hidden2 * num_hidden1); ++x)
  793.     {
  794.       variation = rand () / rand_max * range;
  795.       if ( rand () < (RAND_MAX / 2) )
  796.           variation *= -1.0;
  797.       hidden1_weights [x] += variation;
  798.     }
  799.  
  800.   for (x = 0; x < (num_outputs * num_hidden2); ++x)
  801.     {
  802.       variation = rand () / rand_max * range;
  803.       if ( rand () < (RAND_MAX / 2) )
  804.           variation *= -1.0;
  805.       hidden2_weights [x] += variation;
  806.     }
  807.  
  808. }
  809.  
  810.