home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 624a.lha / Neural_Network_v2.0 / neural_network.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-28  |  23.9 KB  |  816 lines

  1.  
  2. #include <iostream.h>
  3. #include <fstream.h>
  4. #include <new.h>
  5. #include <math.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 (String& 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 (String& filename)
  198. {
  199.   ifstream fp;
  200.   int      x;
  201.   long     iter;
  202.  
  203.   fp.open (filename);
  204.   if ( fp.fail() != 0 )
  205.     {
  206.       cout << "Could not read weights from file " << filename << "\n";
  207.       return (-1);
  208.     }
  209.  
  210.   /* First read in how many iterations have been performed so far */
  211.   fp >> iter;
  212.   cout << "Iterations = " << iter << "\n";
  213.  
  214.   /* Next read in how many input nodes, hidden1 nodes, hidden2 nodes */
  215.   /* and output nodes. */
  216.   fp >> 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 >> 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 >> 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 >> hidden2_weights [x];
  244.     }
  245.  
  246.   fp.close ();
  247.  
  248.   /* Now all the weights have been loaded */
  249.  return (0);
  250. }
  251.  
  252.  
  253.  
  254. int Neural_network::save_weights (String& filename)
  255. {
  256.   ofstream fp;
  257.   int      x;
  258.  
  259.   fp.open (filename);
  260.   if ( fp.fail() != 0 )
  261.     {
  262.       cout << "Could not save weights to file " << filename << "\n";
  263.       return (-1);
  264.     }
  265.  
  266.   /* First write out how many iterations have been performed so far */
  267.   fp << training_examples << "\n";
  268.  
  269.   /* Next write out how many input nodes, hidden1 nodes, hidden2 nodes */
  270.   /* and output nodes. */
  271.   fp << num_inputs << " " << num_hidden1 << " " << num_hidden2 << " ";
  272.   fp << num_outputs << "\n";
  273.  
  274.   fp.precision (6);
  275.   /* Write input->hidden1 weights to output. */
  276.   for (x = 0; x < num_inputs * num_hidden1; ++x)
  277.     {
  278.       fp.width (10);
  279.       fp << input_weights [x] << " ";
  280.       if ( (x % 5) == 4 )
  281.           fp << "\n";
  282.     }
  283.   fp << "\n\n";
  284.  
  285.   /* Write hidden1->hidden2 weights to output. */
  286.   for (x = 0; x < num_hidden1 * num_hidden2; ++x)
  287.     {
  288.       fp.width (10);
  289.       fp << hidden1_weights [x] << " ";
  290.       if ( (x % 5) == 4 )
  291.           fp << "\n";
  292.     }
  293.   fp << "\n\n";
  294.  
  295.   /* Write hidden2->output weights to output. */
  296.   for (x = 0; x < (num_hidden2 * num_outputs); ++x)
  297.     {
  298.       fp.width (10);
  299.       fp << hidden2_weights [x] << " ";
  300.       if ( (x % 5) == 4 )
  301.           fp << "\n";
  302.     }
  303.   fp << "\n\n";
  304.  
  305.   fp.close ();
  306.   cout << "Closed file\n";
  307.  
  308.   /* Now all the weights have been saved */
  309.   return (0);
  310. }
  311.  
  312.  
  313.  
  314. void Neural_network::set_size_parameters (int number_inputs,
  315.                                  int number_hidden1, int number_hidden2,
  316.                                  int number_outputs, double range)
  317. {
  318.   double *new_input_weights,*new_hidden1_weights,*new_hidden2_weights;
  319.   double rand_max;
  320.   int    x;
  321.  
  322.   rand_max = RAND_MAX;
  323.  
  324.   // Allocate new weight matrices with new size
  325.   new_input_weights = new double [number_hidden1 * number_inputs];
  326.   new_hidden1_weights = new double [number_hidden2 * number_hidden1];
  327.   new_hidden2_weights = new double [number_outputs * number_hidden2];
  328.  
  329.   // Copy over all weights
  330.   // Input weights
  331.   for (x = 0; x < number_hidden1 * number_inputs; ++x)
  332.     {
  333.       // IF the new size is larger than the old size, THEN make new connections
  334.       // a random weight between +-range.
  335.       if ( x >= (num_hidden1 * num_inputs) )
  336.         {
  337.           new_input_weights [x] = rand () / rand_max * range;
  338.           if ( rand () < (RAND_MAX / 2) )
  339.               new_input_weights [x] *= -1.0;
  340.         }
  341.       else
  342.           new_input_weights [x] = input_weights [x];
  343.     }
  344.  
  345.   // Hidden1 weights
  346.   for (x = 0; x < number_hidden2 * number_hidden1; ++x)
  347.     {
  348.       // IF the new size is larger than the old size, THEN make new connections
  349.       // a random weight between +-range.
  350.       if ( x >= (num_hidden2 * num_hidden1) )
  351.         {
  352.           new_hidden1_weights [x] = rand () / rand_max * range;
  353.           if ( rand () < (RAND_MAX / 2) )
  354.               new_hidden1_weights [x] *= -1.0;
  355.         }
  356.       else
  357.           new_hidden1_weights [x] = hidden1_weights [x];
  358.     }
  359.  
  360.   // Hidden2 weights
  361.   for (x = 0; x < number_outputs * number_hidden2; ++x)
  362.     {
  363.       // IF the new size is larger than the old size, THEN make new connections
  364.       // a random weight between +-range.
  365.       if ( x >= (num_outputs * num_hidden2) )
  366.         {
  367.           new_hidden2_weights [x] = rand () / rand_max * range;
  368.           if ( rand () < (RAND_MAX / 2) )
  369.               new_hidden2_weights [x] *= -1.0;
  370.         }
  371.       else
  372.           new_hidden2_weights [x] = hidden2_weights [x];
  373.     }
  374.  
  375.   // All weights have been copied.
  376.  
  377.   // Change size paramters
  378.   num_inputs = number_inputs;
  379.   num_hidden1 = number_hidden1;
  380.   num_hidden2 = number_hidden2;
  381.   num_outputs = number_outputs;
  382.  
  383.   // Deallocate all matrices
  384.   deallocate_matrices ();
  385.  
  386.   // Allocate new nerual network matrices with the correct size and initialize
  387.   allocate_matrices ();
  388.   initialize_matrices (1.0);
  389.  
  390.   // Now deallocate new randomly initialized weight matrices and assign them
  391.   // to the new weight matrices that have the correct weight values.
  392.   delete input_weights;
  393.   delete hidden1_weights;
  394.   delete hidden2_weights;
  395.  
  396.   input_weights = new_input_weights;
  397.   hidden1_weights = new_hidden1_weights;
  398.   hidden2_weights = new_hidden2_weights;
  399.  
  400. }
  401.  
  402.  
  403. void Neural_network::back_propagation (double input [],
  404.                                        double desired_output [],
  405.                                        int& done)
  406. {
  407.   int     x,y;
  408.   int     size;
  409.   double  delta,sum_delta,*weight,*p_sum_delta,*p_learning_delta;
  410.  
  411.   /* First check if training complete. */
  412.   for (x = num_outputs - 1; x >= 0; --x)
  413.     {
  414.       if ( fabs (desired_output [x] - output_act [x]) > epsilon )
  415.         {
  416.           done = 0;
  417.         }
  418.     }
  419.  
  420.   /* Go backward through list for speed */
  421.   size = num_hidden2;
  422.   /* First calculate deltas of weights from output to hidden layer 2. */
  423.   for (x = num_outputs - 1; x >= 0; --x)
  424.     {
  425.       weight = &hidden2_weights [x * size];
  426.       p_sum_delta = &hidden2_weights_sum_delta [x * size];
  427.       p_learning_delta = &hidden2_learning_delta [x * size];
  428.       for (y = num_hidden2 - 1; y >= 0; --y)
  429.         {
  430.           /* Formula delta = (desired - actual) * derivative
  431.              derivative = S(1 - S)
  432.              Also calculate sum of deltas * weight for next layer.
  433.           */
  434.           delta = (desired_output [x] - output_act [x])
  435.                    * SLOPE * output_act [x] * (1.0 - output_act [x]);
  436.  
  437.           hidden2_sum_delta_weight [y] += delta * weight [y];
  438.  
  439.           p_learning_delta [y] += delta;
  440.  
  441.           /* Now multiply by activation and sum in weights sum delta */
  442.           p_sum_delta [y] += delta * hidden2_act [y];
  443.         }
  444.     }
  445.  
  446.  
  447.   /* Next calculate deltas of weights between hidden layer2 and hidden
  448.      layer 1 */
  449.   size = num_hidden1;
  450.   for (x = num_hidden2 - 1; x >= 0; --x)
  451.     {
  452.       sum_delta = hidden2_sum_delta_weight [x];
  453.       weight = &hidden1_weights [x * size];
  454.       p_sum_delta = &hidden1_weights_sum_delta [x * size];
  455.       p_learning_delta = &hidden1_learning_delta [x * size];
  456.       for (y = num_hidden1 - 1; y >= 0; --y)
  457.         {
  458.           /* Formula delta = SUM (previous deltas*weight)
  459.                              * derivative
  460.              previous deltas already muliplied by weight.
  461.              derivative = S(1 - S)
  462.  
  463.              Also calculate sum of deltas * weight to save from doing
  464.              it for next layer.
  465.           */
  466.  
  467.           delta = sum_delta * hidden2_act [x] *
  468.                   (1.0 - hidden2_act [x]) * SLOPE;
  469.  
  470.           hidden1_sum_delta_weight [y] += delta * weight [y];
  471.  
  472.           p_learning_delta [y] += delta;
  473.  
  474.           /* Now multiply by activation and sum in weights_sum_delta */
  475.           p_sum_delta [y] += delta * hidden1_act [y];
  476.         }
  477.       hidden2_sum_delta_weight [x] = 0.0;
  478.     }
  479.  
  480.   /* Finally calculate deltas of weights between hidden layer 1 and input
  481.      layer */
  482.   size = num_inputs;
  483.   for (x = num_hidden1 - 1; x >= 0; --x)
  484.     {
  485.       sum_delta = hidden1_sum_delta_weight [x];
  486.       p_sum_delta = &input_weights_sum_delta [x * size];
  487.       p_learning_delta = &input_learning_delta [x * size];
  488.       for (y = num_inputs - 1; y >= 0; --y)
  489.         {
  490.           /* Formula delta = SUM (previous deltas*weight)
  491.                              * derivative * activation of input
  492.              previous deltas already muliplied by weight
  493.              derivative = S(1 - S)
  494.           */
  495.           delta = sum_delta * hidden1_act [x] *
  496.                   (1.0 - hidden1_act [x]) * SLOPE;
  497.  
  498.           p_learning_delta [y] += delta;
  499.  
  500.           p_sum_delta [y] += (delta * input [y]);
  501.         }
  502.       hidden1_sum_delta_weight [x] = 0.0;
  503.     }
  504.  
  505.   /* Now all deltas have been calculated and added into their appropriate
  506.      neuron connection. */
  507.   ++examples_since_update;
  508.  
  509. }
  510.  
  511.  
  512. double Neural_network::calc_forward (double input [], double desired_output [],
  513.                                      int& num_wrong, int& skip, int print_it,
  514.                                      int& actual_printed)
  515. {
  516.   int     x,y,wrong;
  517.   int     size;
  518.   double  *weight,error,abs_error;
  519.  
  520.   skip = 1;
  521.   wrong = 0;
  522.   error = 0.0;
  523.  
  524.   /* Go backward for faster processing */
  525.   /* Calculate hidden layer 1's activation */
  526.   size = num_inputs;
  527.   for (x = num_hidden1 - 1; x >= 0;  --x)
  528.     {
  529.       hidden1_act [x] = 0.0;
  530.       weight = &input_weights [x * size];
  531.       for (y = num_inputs - 1; y >= 0; --y)
  532.         {
  533.           hidden1_act [x] += (input [y] * weight [y]);
  534.         }
  535.       hidden1_act [x] = S(hidden1_act [x]);
  536.     }
  537.  
  538.   /* Calculate hidden layer 2's activation */
  539.   size = num_hidden1;
  540.   for (x = num_hidden2 - 1; x >= 0; --x)
  541.     {
  542.       hidden2_act [x] = 0.0;
  543.       weight = &hidden1_weights [x * size];
  544.       for (y = num_hidden1 - 1; y >= 0; --y)
  545.         {
  546.           hidden2_act [x] += (hidden1_act [y] * weight [y]);
  547.         }
  548.       hidden2_act [x] = S(hidden2_act [x]);
  549.     }
  550.  
  551.   /* Calculate output layer's activation */
  552.   size = num_hidden2;
  553.   for (x = num_outputs - 1; x >= 0; --x)
  554.     {
  555.       output_act [x] = 0.0;
  556.       weight = &hidden2_weights [x * size];
  557.       for (y = num_hidden2 - 1; y >= 0; --y)
  558.         {
  559.           output_act [x] += hidden2_act [y] * weight [y];
  560.         }
  561.       output_act [x] = S(output_act [x]);
  562.       abs_error = fabs (output_act [x] - desired_output [x]);
  563.       error += abs_error;
  564.       if ( abs_error > epsilon )
  565.           wrong = 1;
  566.       if ( abs_error > skip_epsilon )
  567.           skip = 0;
  568.     }
  569.  
  570.   if ( wrong )
  571.       ++num_wrong;
  572.  
  573.   cout.precision (3);
  574.   if ( print_it == 2 )
  575.     {
  576.       for (x = 0; x < num_outputs; ++x)
  577.         {
  578.           cout.width (6);
  579.           cout << output_act [x] << " ";
  580.         }
  581.       ++actual_printed;
  582.     }
  583.   else if ( print_it && wrong )
  584.     {
  585.       for (x = 0; x < num_outputs; ++x)
  586.         {
  587.           cout.width (6);
  588.           cout << fabs (desired_output [x] - output_act [x]) << " ";
  589.         }
  590.       ++actual_printed;
  591.     }
  592.  
  593.   return (error);
  594.  
  595. }
  596.  
  597.  
  598. void Neural_network::update_weights ()
  599. {
  600.   int     x,y;
  601.   int     size;
  602.   double  rate,*p_ldelta,*p_ldelta_bar,*weight,*p_lrate,*p_sum_delta;
  603.  
  604.   // Check to see if any changes have been calculated.
  605.   if ( examples_since_update == 0 )
  606.     {
  607.       return;
  608.     }
  609.  
  610.   /* Go backward for slightly faster processing */
  611.   /* First add deltas of weights from output to hidden layer 2. */
  612.   size = num_hidden2;
  613.   for (x = num_outputs - 1; x >= 0; --x)
  614.     {
  615.       p_ldelta = &hidden2_learning_delta [x * size];
  616.       p_ldelta_bar = &hidden2_learning_delta_bar [x * size];
  617.       weight = &hidden2_weights [x * size];
  618.       p_lrate = &hidden2_learning_rate [x * size];
  619.       p_sum_delta = &hidden2_weights_sum_delta [x * size];
  620.  
  621.       for (y = num_hidden2 - 1; y >= 0; --y)
  622.         {
  623.           rate = p_ldelta [y] * p_ldelta_bar [y];
  624.           if ( rate < 0.0 )
  625.             {
  626.               p_lrate [y] -= (phi * p_lrate [y]);
  627.             }
  628.           else if ( rate > 0.0 )
  629.             {
  630.               p_lrate [y] += K;
  631.             }
  632.  
  633.           weight [y] += (p_lrate [y] * p_sum_delta [y]);
  634.           p_sum_delta [y] = 0.0;
  635.           p_ldelta_bar [y] *= theta;
  636.           p_ldelta_bar [y] += ((1.0 - theta) * p_ldelta [y]);
  637.           p_ldelta [y] = 0.0;
  638.         }
  639.     }
  640.  
  641.   /* Next add deltas of weights between hidden layer2 and hidden
  642.      layer 1 */
  643.   size = num_hidden1;
  644.   for (x = num_hidden2 - 1; x >= 0; --x)
  645.     {
  646.       p_ldelta = &hidden1_learning_delta [x * size];
  647.       p_ldelta_bar = &hidden1_learning_delta_bar [x * size];
  648.       weight = &hidden1_weights [x * size];
  649.       p_lrate = &hidden1_learning_rate [x * size];
  650.       p_sum_delta = &hidden1_weights_sum_delta [x * size];
  651.  
  652.       for (y = num_hidden1 - 1; y >= 0; --y)
  653.         {
  654.           rate = p_ldelta [y] * p_ldelta_bar [y];
  655.           if ( rate < 0.0 )
  656.             {
  657.               p_lrate [y] -= (phi * p_lrate [y]);
  658.             }
  659.           else if ( rate > 0.0 )
  660.             {
  661.               p_lrate [y] += K;
  662.             }
  663.  
  664.           weight [y] += (p_lrate [y] * p_sum_delta [y]);
  665.           p_sum_delta [y] = 0.0;
  666.           p_ldelta_bar [y] *= theta;
  667.           p_ldelta_bar [y] += ((1.0 - theta) * p_ldelta [y]);
  668.           p_ldelta [y] = 0.0;
  669.         }
  670.     }
  671.  
  672.   /* Finally add deltas of weights between hidden layer 1 and input
  673.      layer */
  674.   size = num_inputs;
  675.   for (x = num_hidden1 - 1; x >= 0; --x)
  676.     {
  677.       p_ldelta = &input_learning_delta [x * size];
  678.       p_ldelta_bar = &input_learning_delta_bar [x * size];
  679.       weight = &input_weights [x * size];
  680.       p_lrate = &input_learning_rate [x * size];
  681.       p_sum_delta = &input_weights_sum_delta [x * size];
  682.  
  683.       for (y = num_inputs - 1; y >= 0; --y)
  684.         {
  685.           rate = p_ldelta [y] * p_ldelta_bar [y];
  686.           if ( rate < 0.0 )
  687.             {
  688.               p_lrate [y] -= (phi * p_lrate [y]);
  689.             }
  690.           else if ( rate > 0.0 )
  691.             {
  692.               p_lrate [y] += K;
  693.             }
  694.  
  695.           weight [y] += (p_lrate [y] * p_sum_delta [y]);
  696.           p_sum_delta [y] = 0.0;
  697.           p_ldelta_bar [y] *= theta;
  698.           p_ldelta_bar [y] += ((1.0 - theta) * p_ldelta [y]);
  699.           p_ldelta [y] = 0.0;
  700.         }
  701.     }
  702.  
  703.   /* Now all deltas have been added into their appropriate neuron
  704.      connection. */
  705.   training_examples += examples_since_update;
  706.   examples_since_update = 0;
  707.  
  708. }
  709.  
  710.  
  711. int Neural_network::calc_forward_test (double input [],
  712.                                        double desired_output [],
  713.                                        int print_it, double correct_eps,
  714.                                        double good_eps)
  715. {
  716.   int x,y,wrong,good;
  717.  
  718.   wrong = 0;
  719.   good = 0;
  720.  
  721.   /* Go backward for faster processing */
  722.   /* Calculate hidden layer 1's activation */
  723.   for (x = num_hidden1 - 1; x >= 0;  --x)
  724.     {
  725.       hidden1_act [x] = 0.0;
  726.       for (y = num_inputs - 1; y >= 0; --y)
  727.         {
  728.           hidden1_act [x] += (input [y] *
  729.                               input_weights [x * num_inputs + y]);
  730.         }
  731.       hidden1_act [x] = S(hidden1_act [x]);
  732.     }
  733.  
  734.   /* Calculate hidden layer 2's activation */
  735.   for (x = num_hidden2 - 1; x >= 0; --x)
  736.     {
  737.       hidden2_act [x] = 0.0;
  738.       for (y = num_hidden1 - 1; y >= 0; --y)
  739.         {
  740.           hidden2_act [x] += (hidden1_act [y] *
  741.                                  hidden1_weights [x*num_hidden1 + y]);
  742.         }
  743.       hidden2_act [x] = S(hidden2_act [x]);
  744.     }
  745.  
  746.   /* Calculate output layer's activation */
  747.   for (x = num_outputs - 1; x >= 0; --x)
  748.     {
  749.       output_act [x] = 0.0;
  750.       for (y = num_hidden2 - 1; y >= 0; --y)
  751.         {
  752.           output_act [x] += hidden2_act [y] *
  753.                                 hidden2_weights [x * num_hidden2 + y];
  754.         }
  755.       output_act [x] = S(output_act [x]);
  756.  
  757.       if ( fabs (output_act [x] - desired_output [x]) > good_eps )
  758.           wrong = 1;
  759.       else if ( fabs (output_act [x] - desired_output [x]) > correct_eps )
  760.           good = 1;
  761.     }
  762.  
  763.   cout.precision(3);
  764.   if ( print_it )
  765.     {
  766.       for (x = 0; x < num_outputs; ++x)
  767.         {
  768.           cout.width (6);
  769.           cout << output_act [x] << " ";
  770.         }
  771.     }
  772.  
  773.   if ( wrong )
  774.       return (WRONG);
  775.   else if ( good )
  776.       return (GOOD);
  777.   else
  778.       return (CORRECT);
  779. }
  780.  
  781.  
  782. void Neural_network::kick_weights (double range)
  783. {
  784.   int    x;
  785.   double rand_max;
  786.   double variation;
  787.  
  788.   rand_max = RAND_MAX;
  789.   /* Add from -range to +range to all weights randomly */
  790.   for (x = 0; x < (num_hidden1 * num_inputs); ++x)
  791.     {
  792.       variation = rand () / rand_max * range;
  793.       if ( rand () < (RAND_MAX / 2) )
  794.           variation *= -1.0;
  795.       input_weights [x] += variation;
  796.     }
  797.  
  798.   for (x = 0; x < (num_hidden2 * num_hidden1); ++x)
  799.     {
  800.       variation = rand () / rand_max * range;
  801.       if ( rand () < (RAND_MAX / 2) )
  802.           variation *= -1.0;
  803.       hidden1_weights [x] += variation;
  804.     }
  805.  
  806.   for (x = 0; x < (num_outputs * num_hidden2); ++x)
  807.     {
  808.       variation = rand () / rand_max * range;
  809.       if ( rand () < (RAND_MAX / 2) )
  810.           variation *= -1.0;
  811.       hidden2_weights [x] += variation;
  812.     }
  813.  
  814. }
  815.  
  816.