home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 618a.lha / NeuralNetwork / neural_net.c < prev    next >
C/C++ Source or Header  |  1992-03-08  |  31KB  |  1,012 lines

  1.  
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <stdlib.h>
  5. #include "Neural_net.h"
  6.  
  7. static void Neural_net_allocate_matrices (Neural_net *nn);
  8. static void Neural_net_initialize_matrices (Neural_net *nn,
  9.                                            double range);
  10. static void Neural_net_deallocate_matrices (Neural_net *nn);
  11.  
  12. static void Neural_net_allocate_matrices (Neural_net *nn)
  13. {
  14.  
  15.   /* Time to allocate the entire neural_net structure
  16.   // Activation matrices */
  17.   nn->hidden1_act = (double *) malloc (sizeof (double) * nn->num_hidden1);
  18.   nn->hidden2_act = (double *) malloc (sizeof (double) * nn->num_hidden2);
  19.   nn->output_act = (double *) malloc (sizeof (double) * nn->num_outputs);
  20.  
  21.   /* Weight matrices */
  22.   nn->input_weights = (double *) malloc (sizeof (double) * nn->num_hidden1 *
  23.                                          nn->num_inputs);
  24.   nn->hidden1_weights = (double *) malloc (sizeof (double) * nn->num_hidden2 *
  25.                                            nn->num_hidden1);
  26.   nn->hidden2_weights = (double *) malloc (sizeof (double) * nn->num_outputs *
  27.                                            nn->num_hidden2);
  28.  
  29.   /* Learning rate matrices for each weight's learning rate.
  30.   // Needed for delta-bar-delta algorithm */
  31.   nn->input_learning_rate = (double *) malloc (sizeof (double) *
  32.                                                nn->num_hidden1 * nn->num_inputs);
  33.   nn->hidden1_learning_rate = (double *) malloc (sizeof (double) *
  34.                                                  nn->num_hidden2 * nn->num_hidden1);
  35.   nn->hidden2_learning_rate = (double *) malloc (sizeof (double) *
  36.                                                  nn->num_outputs * nn->num_hidden2);
  37.  
  38.   /* Learning rate deltas for each weight's learning rate.
  39.   // Needed for delta-bar-delta algorithm. */
  40.   nn->input_learning_delta = (double *) malloc (sizeof (double) *
  41.                                                 nn->num_hidden1 * nn->num_inputs);
  42.   nn->hidden1_learning_delta = (double *) malloc (sizeof (double) *
  43.                                                   nn->num_hidden2 * nn->num_hidden1);
  44.   nn->hidden2_learning_delta = (double *) malloc (sizeof (double) *
  45.                                                   nn->num_outputs * nn->num_hidden2);
  46.  
  47.   /* Delta bar matrices for each weight's delta bar.
  48.   // Needed for delta-bar-delta algorithm. */
  49.   nn->input_learning_delta_bar = (double *) malloc (sizeof (double) *
  50.                                                     nn->num_hidden1 * nn->num_inputs);
  51.   nn->hidden1_learning_delta_bar = (double *) malloc (sizeof (double) *
  52.                                                    nn->num_hidden2 * nn->num_hidden1);
  53.   nn->hidden2_learning_delta_bar = (double *) malloc (sizeof (double) *
  54.                                                    nn->num_outputs * nn->num_hidden2);
  55.  
  56.   /* Weight delta matrices for each weights delta.
  57.   // Needed for BackPropagation algorithm. */
  58.   nn->input_weights_sum_delta = (double *) malloc (sizeof (double) *
  59.                                                    nn->num_hidden1 * nn->num_inputs);
  60.   nn->hidden1_weights_sum_delta = (double *) malloc (sizeof (double) *
  61.                                                    nn->num_hidden2 * nn->num_hidden1);
  62.   nn->hidden2_weights_sum_delta = (double *) malloc (sizeof (double) *
  63.                                                    nn->num_outputs * nn->num_hidden2);
  64.  
  65.   /* Sum of delta * weight matrices for each weight.
  66.   // Needed for BackPropagation algorithm. */
  67.   nn->hidden1_sum_delta_weight = (double *) malloc (sizeof (double) *
  68.                                                     nn->num_hidden2 * nn->num_hidden1);
  69.   nn->hidden2_sum_delta_weight = (double *) malloc (sizeof (double) *
  70.                                                     nn->num_outputs * nn->num_hidden2);
  71.  
  72.   /* Done neural net allocation */
  73. }
  74.  
  75. static void Neural_net_initialize_matrices (Neural_net *nn,
  76.                                             double range)
  77. {
  78.   int    x,y;
  79.   double rand_max;
  80.  
  81.   nn->training_examples = 0;
  82.   nn->examples_since_update = 0;
  83.  
  84.   rand_max = RAND_MAX;
  85.   /* Initialize all weights from -range to +range randomly */
  86.   for (x = 0; x < nn->num_hidden1; ++x)
  87.     {
  88.       nn->hidden1_sum_delta_weight [x] = 0.0;
  89.  
  90.       for (y = 0; y < nn->num_inputs; ++y)
  91.         {
  92.           nn->input_weights [x * nn->num_inputs + y] = rand () / rand_max * range;
  93.           if ( rand () < (RAND_MAX / 2) )
  94.               nn->input_weights [x * nn->num_inputs + y] *= -1.0;
  95.  
  96.           nn->input_weights_sum_delta [x * nn->num_inputs + y] = 0.0;
  97.           nn->input_learning_rate [x * nn->num_inputs + y] = nn->learning_rate;
  98.           nn->input_learning_delta [x * nn->num_inputs + y] = 0.0;
  99.           nn->input_learning_delta_bar [x * nn->num_inputs + y] = 0.0;
  100.         }
  101.     }
  102.  
  103.   for (x = 0; x < nn->num_hidden2; ++x)
  104.     {
  105.       nn->hidden2_sum_delta_weight [x] = 0.0;
  106.  
  107.       for (y = 0; y < nn->num_hidden1; ++y)
  108.         {
  109.           nn->hidden1_weights [x * nn->num_hidden1 + y] = rand () / rand_max * range;
  110.           if ( rand () < (RAND_MAX / 2) )
  111.               nn->hidden1_weights [x * nn->num_hidden1 + y] *= -1.0;
  112.  
  113.           nn->hidden1_weights_sum_delta [x * nn->num_hidden1 + y] = 0.0;
  114.           nn->hidden1_learning_rate [x * nn->num_hidden1 + y] = nn->learning_rate;
  115.           nn->hidden1_learning_delta [x * nn->num_hidden1 + y] = 0.0;
  116.           nn->hidden1_learning_delta_bar [x * nn->num_hidden1 + y] = 0.0;
  117.         }
  118.     }
  119.  
  120.   for (x = 0; x < nn->num_outputs; ++x)
  121.     {
  122.       for (y = 0; y < nn->num_hidden2; ++y)
  123.         {
  124.           nn->hidden2_weights [x * nn->num_hidden2 + y] = rand () / rand_max * range;
  125.           if ( rand () < (RAND_MAX / 2) )
  126.               nn->hidden2_weights [x * nn->num_hidden2 + y] *= -1.0;
  127.  
  128.           nn->hidden2_weights_sum_delta [x * nn->num_hidden2 + y] = 0.0;
  129.           nn->hidden2_learning_rate [x * nn->num_hidden2 + y] = nn->learning_rate;
  130.           nn->hidden2_learning_delta [x * nn->num_hidden2 + y] = 0.0;
  131.           nn->hidden2_learning_delta_bar [x * nn->num_hidden2 + y] = 0.0;
  132.         }
  133.     }
  134.  
  135. }
  136.  
  137. static void Neural_net_deallocate_matrices (Neural_net *nn)
  138. {
  139.  
  140.   if ( nn->hidden1_act == NULL )
  141.       return;
  142.  
  143.   /* Time to destroy the entire neural_net structure
  144.   // Activation matrices */
  145.   free (nn->hidden1_act);
  146.   free (nn->hidden2_act);
  147.   free (nn->output_act);
  148.  
  149.   /* Weight matrices */
  150.   free (nn->input_weights);
  151.   free (nn->hidden1_weights);
  152.   free (nn->hidden2_weights);
  153.  
  154.   /* Learning rate matrices for each weight's learning rate.
  155.   // Needed for delta-bar-delta algorithm */
  156.   free (nn->input_learning_rate);
  157.   free (nn->hidden1_learning_rate);
  158.   free (nn->hidden2_learning_rate);
  159.  
  160.   /* Learning rate deltas for each weight's learning rate.
  161.   // Needed for delta-bar-delta algorithm. */
  162.   free (nn->input_learning_delta);
  163.   free (nn->hidden1_learning_delta);
  164.   free (nn->hidden2_learning_delta);
  165.  
  166.   /* Delta bar matrices for each weight's delta bar.
  167.   // Needed for delta-bar-delta algorithm. */
  168.   free (nn->input_learning_delta_bar);
  169.   free (nn->hidden1_learning_delta_bar);
  170.   free (nn->hidden2_learning_delta_bar);
  171.  
  172.   /* Weight delta matrices for each weights delta.
  173.   // Needed for BackPropagation algorithm. */
  174.   free (nn->input_weights_sum_delta);
  175.   free (nn->hidden1_weights_sum_delta);
  176.   free (nn->hidden2_weights_sum_delta);
  177.  
  178.   /* Sum of delta * weight matrices for each weight.
  179.   // Needed for BackPropagation algorithm. */
  180.   free (nn->hidden1_sum_delta_weight);
  181.   free (nn->hidden2_sum_delta_weight);
  182.  
  183.   /* Done neural net deallocation */
  184. }
  185.  
  186. Neural_net *Neural_net_constr (int number_inputs, int number_hidden1,
  187.                            int number_hidden2, int number_outputs,
  188.                            double t_epsilon, double t_skip_epsilon,
  189.                            double t_learning_rate, double t_theta,
  190.                            double t_phi, double t_K, double range)
  191. {
  192.   Neural_net *nn;
  193.  
  194.   if ( (nn = malloc (sizeof (Neural_net))) == NULL )
  195.     {
  196.       return (NULL);
  197.     }
  198.  
  199.   nn->num_inputs = number_inputs;
  200.   nn->num_hidden1 = number_hidden1;
  201.   nn->num_hidden2 = number_hidden2;
  202.   nn->num_outputs = number_outputs;
  203.   nn->epsilon = t_epsilon;
  204.   nn->skip_epsilon = t_skip_epsilon;
  205.   nn->learning_rate = t_learning_rate;
  206.   nn->theta = t_theta;
  207.   nn->phi = t_phi;
  208.   nn->K = t_K;
  209.   nn->training_examples = 0;
  210.   nn->examples_since_update = 0;
  211.  
  212.   Neural_net_allocate_matrices (nn);
  213.   Neural_net_initialize_matrices (nn,range);
  214.  
  215.   return (nn);
  216. }
  217.  
  218.  
  219. Neural_net *Neural_net_read_constr (char *filename, int *file_error,
  220.                                 double t_epsilon, double t_skip_epsilon,
  221.                                 double t_learning_rate, double t_theta,
  222.                                 double t_phi, double t_K)
  223. {
  224.   Neural_net *nn;
  225.  
  226.   if ( (nn = malloc (sizeof (Neural_net))) == NULL )
  227.     {
  228.       return (NULL);
  229.     }
  230.  
  231.   nn->epsilon = t_epsilon;
  232.   nn->skip_epsilon = t_skip_epsilon;
  233.   nn->learning_rate = t_learning_rate;
  234.   nn->theta = t_theta;
  235.   nn->phi = t_phi;
  236.   nn->K = t_K;
  237.   nn->training_examples = 0;
  238.   nn->examples_since_update = 0;
  239.  
  240.   nn->hidden1_act = NULL;
  241.   if ( (*file_error = Neural_net_read_weights (nn,filename)) < 0 )
  242.     {
  243.       free (nn);
  244.       return (NULL);
  245.     }
  246.  
  247.   return (nn);
  248. }
  249.  
  250. #ifndef __inline__
  251. Neural_net *Neural_net_default_constr (int number_inputs, int number_hidden1,
  252.                                        int number_hidden2, int number_outputs)
  253. {
  254.   return (Neural_net_constr (number_inputs,number_hidden1,number_hidden2,
  255.                              number_outputs,0.1,0.05,0.1,1.0,0.0,0.0,1.0));
  256. }
  257.  
  258. Neural_net *Neural_net_default_read_constr (char *filename, int *file_error)
  259. {
  260.   return (Neural_net_read_constr (filename,file_error,0.1,0.05,0.1,1.0,0.0,
  261.                                   0.0));
  262. }
  263. #endif
  264.  
  265.  
  266. void Neural_net_destr (Neural_net *nn)
  267. {
  268.   if ( nn != NULL )
  269.     {
  270.       Neural_net_deallocate_matrices (nn);
  271.       free (nn);
  272.     }
  273. }
  274.  
  275. int Neural_net_read_weights (Neural_net *nn, char *filename)
  276. {
  277.   FILE    *fp;
  278.   int     x;
  279.   long    iter;
  280.  
  281.   if ( ((fp = fopen (filename,"rt")) == NULL) )
  282.     {
  283.       printf ("Could not read weights from file '%s'\n",filename);
  284.       return (-1);
  285.     }
  286.  
  287.   /* First read in how many iterations have been performed so far */
  288.   fscanf (fp,"%ld",&iter);
  289.   printf ("Iterations = %ld\n",iter);
  290.  
  291.   /* Next read in how many input nodes, hidden1 nodes, hidden2 nodes */
  292.   /* and output nodes. */
  293.   fscanf (fp,"%d%d%d%d",&nn->num_inputs,&nn->num_hidden1,&nn->num_hidden2,
  294.                         &nn->num_outputs);
  295.  
  296.   /* Deallocate previous matrices */
  297.   Neural_net_deallocate_matrices (nn);
  298.  
  299.   /* Allocate new matrices with new size */
  300.   Neural_net_allocate_matrices (nn);
  301.  
  302.   /* Initialize all matrices and variables */
  303.   Neural_net_initialize_matrices (nn,1.0);
  304.   nn->training_examples = iter;
  305.  
  306.   /* Read input->hidden1 weights from file. */
  307.   for (x = 0; x < nn->num_inputs * nn->num_hidden1; ++x)
  308.     {
  309.       fscanf (fp,"%lf",&nn->input_weights [x]);
  310.     }
  311.  
  312.   /* Read hidden1->hidden2 weights from file. */
  313.   for (x = 0; x < nn->num_hidden1 * nn->num_hidden2; ++x)
  314.     {
  315.       fscanf (fp,"%lf",&nn->hidden1_weights [x]);
  316.     }
  317.  
  318.   /* Read hidden2->output weights from file. */
  319.   for (x = 0; x < (nn->num_hidden2 * nn->num_outputs); ++x)
  320.     {
  321.       fscanf (fp,"%lf",&nn->hidden2_weights [x]);
  322.     }
  323.  
  324.   /* Now all the weights have been loaded */
  325.  fclose (fp);
  326.  
  327.  return (0);
  328. }
  329.  
  330.  
  331.  
  332. int Neural_net_save_weights (Neural_net *nn, char *filename)
  333. {
  334.   FILE *fp;
  335.   int   x;
  336.  
  337.   if ( ((fp = fopen (filename,"wt")) == NULL) )
  338.     {
  339.       printf ("Could not save weights to file '%s'\n",filename);
  340.       return (-1);
  341.     }
  342.  
  343.   /* First write out how many iterations have been performed so far */
  344.   fprintf (fp," %ld\n",nn->training_examples);
  345.  
  346.   /* Next write out how many input nodes, hidden1 nodes, hidden2 nodes */
  347.   /* and output nodes. */
  348.   fprintf (fp," %d %d %d %d\n",nn->num_inputs,nn->num_hidden1,
  349.            nn->num_hidden2,nn->num_outputs);
  350.  
  351.   /* Write input->hidden1 weights to output. */
  352.   for (x = 0; x < nn->num_inputs * nn->num_hidden1; ++x)
  353.     {
  354.       fprintf (fp,"%10.5f ",nn->input_weights [x]);
  355.       if ( (x % 5) == 4 )
  356.           fprintf (fp,"\n");
  357.     }
  358.   fprintf (fp,"\n\n");
  359.  
  360.   /* Write hidden1->hidden2 weights to output. */
  361.   for (x = 0; x < nn->num_hidden1 * nn->num_hidden2; ++x)
  362.     {
  363.       fprintf (fp,"%10.5f ",nn->hidden1_weights [x]);
  364.       if ( (x % 5) == 4 )
  365.           fprintf (fp,"\n");
  366.     }
  367.   fprintf (fp,"\n\n");
  368.  
  369.   /* Write hidden2->output weights to output. */
  370.   for (x = 0; x < (nn->num_hidden2 * nn->num_outputs); ++x)
  371.     {
  372.       fprintf (fp,"%10.5f ",nn->hidden2_weights [x]);
  373.       if ( (x % 5) == 4 )
  374.           fprintf (fp,"\n");
  375.     }
  376.   fprintf (fp,"\n\n");
  377.  
  378.   fflush (fp);
  379.   printf ("Flushed file\n");
  380.   fclose (fp);
  381.   printf ("Closed file\n");
  382.  
  383.   /* Now all the weights have been saved */
  384.   return (0);
  385. }
  386.  
  387.  
  388. #ifndef __inline__
  389. double Neural_net_get_hidden1_activation (Neural_net *nn, int node)
  390. {
  391.   return (nn->hidden1_act [node]);
  392. }
  393.  
  394. double Neural_net_get_hidden2_activation (Neural_net *nn, int node)
  395. {
  396.   return (nn->hidden2_act [node]);
  397. }
  398.  
  399. double Neural_net_get_output_activation (Neural_net *nn, int node)
  400. {
  401.   return (nn->output_act [node]);
  402. }
  403.  
  404. double Neural_net_get_input_weight (Neural_net *nn, int input_node,
  405.                                     int hidden1_node)
  406. {
  407.   return (nn->input_weights [hidden1_node * nn->num_inputs + input_node]);
  408. }
  409.  
  410. double Neural_net_get_hidden1_weight (Neural_net *nn, int hidden1_node,
  411.                                       int hidden2_node)
  412. {
  413.   return (nn->hidden1_weights [hidden2_node * nn->num_hidden1 +
  414.                                hidden1_node]);
  415. }
  416.  
  417. double Neural_net_get_hidden2_weight (Neural_net *nn, int hidden2_node,
  418.                                       int output_node)
  419. {
  420.   return (nn->hidden2_weights [output_node*nn->num_hidden2+hidden2_node]);
  421. };
  422.  
  423. #endif
  424.  
  425. void Neural_net_set_size_parameters (Neural_net *nn, int number_inputs,
  426.                                      int number_hidden1, int number_hidden2,
  427.                                      int number_outputs, double range)
  428. {
  429.   double *new_input_weights,*new_hidden1_weights;
  430.   double *new_hidden2_weights;
  431.   double rand_max;
  432.   int    x;
  433.  
  434.   rand_max = RAND_MAX;
  435.  
  436.   /* Allocate new weight matrices with new size */
  437.   new_input_weights = (double *) malloc (sizeof (double) *
  438.                                      number_hidden1 * number_inputs);
  439.   new_hidden1_weights = (double *) malloc (sizeof (double) *
  440.                                        number_hidden2 * number_hidden1);
  441.   new_hidden2_weights = (double *) malloc (sizeof (double) *
  442.                                        number_outputs * number_hidden2);
  443.  
  444.   /* Copy over all weights
  445.   // Input weights */
  446.   for (x = 0; x < number_hidden1 * number_inputs; ++x)
  447.     {
  448.       /* IF the new size is larger than the old size, THEN make new connections
  449.       // a random weight between +-range. */
  450.       if ( x >= (nn->num_hidden1 * nn->num_inputs) )
  451.         {
  452.           new_input_weights [x] = rand () / rand_max * range;
  453.           if ( rand () < (RAND_MAX / 2) )
  454.               new_input_weights [x] *= -1.0;
  455.         }
  456.       else
  457.           new_input_weights [x] = nn->input_weights [x];
  458.     }
  459.  
  460.   /* Hidden1 weights */
  461.   for (x = 0; x < number_hidden2 * number_hidden1; ++x)
  462.     {
  463.       /* IF the new size is larger than the old size, THEN make new connections
  464.       // a random weight between +-range. */
  465.       if ( x >= (nn->num_hidden2 * nn->num_hidden1) )
  466.         {
  467.           new_hidden1_weights [x] = rand () / rand_max * range;
  468.           if ( rand () < (RAND_MAX / 2) )
  469.               new_hidden1_weights [x] *= -1.0;
  470.         }
  471.       else
  472.           new_hidden1_weights [x] = nn->hidden1_weights [x];
  473.     }
  474.  
  475.   /* Hidden2 weights */
  476.   for (x = 0; x < number_outputs * number_hidden2; ++x)
  477.     {
  478.       /* IF the new size is larger than the old size, THEN make new connections
  479.       // a random weight between +-range. */
  480.       if ( x >= (nn->num_outputs * nn->num_hidden2) )
  481.         {
  482.           new_hidden2_weights [x] = rand () / rand_max * range;
  483.           if ( rand () < (RAND_MAX / 2) )
  484.               new_hidden2_weights [x] *= -1.0;
  485.         }
  486.       else
  487.           new_hidden2_weights [x] = nn->hidden2_weights [x];
  488.     }
  489.  
  490.   /* All weights have been copied. */
  491.  
  492.   /* Change size paramters */
  493.   nn->num_inputs = number_inputs;
  494.   nn->num_hidden1 = number_hidden1;
  495.   nn->num_hidden2 = number_hidden2;
  496.   nn->num_outputs = number_outputs;
  497.  
  498.   /* Deallocate all matrices */
  499.   Neural_net_deallocate_matrices (nn);
  500.  
  501.   /* Allocate new nerual network matrices with the correct size and initialize */
  502.   Neural_net_allocate_matrices (nn);
  503.   Neural_net_initialize_matrices (nn,1.0);
  504.  
  505.   /* Now deallocate new randomly initialized weight matrices and assign them
  506.   // to the new weight matrices that have the correct weight values. */
  507.   free (nn->input_weights);
  508.   free (nn->hidden1_weights);
  509.   free (nn->hidden2_weights);
  510.  
  511.   nn->input_weights = new_input_weights;
  512.   nn->hidden1_weights = new_hidden1_weights;
  513.   nn->hidden2_weights = new_hidden2_weights;
  514.  
  515. }
  516.  
  517. #ifndef __inline__
  518. int Neural_net_get_number_inputs (Neural_net *nn)
  519. {
  520.   return (nn->num_inputs);
  521. }
  522.  
  523. int Neural_net_get_number_hidden1 (Neural_net *nn)
  524. {
  525.   return (nn->num_hidden1);
  526. }
  527.  
  528. int Neural_net_get_number_hidden2 (Neural_net *nn)
  529. {
  530.   return (nn->num_hidden2);
  531. }
  532.  
  533. int Neural_net_get_number_outputs (Neural_net *nn)
  534. {
  535.   return (nn->num_outputs);
  536. }
  537.  
  538. void Neural_net_set_epsilon (Neural_net *nn, double eps)
  539. {
  540.   nn->epsilon = eps;
  541. }
  542.  
  543. void Neural_net_set_skip_epsilon (Neural_net *nn, double eps)
  544. {
  545.   nn->skip_epsilon = eps;
  546. }
  547.  
  548. void Neural_net_set_learning_rate (Neural_net *nn, double l_rate)
  549. {
  550.   nn->learning_rate = l_rate;
  551. }
  552.  
  553. void Neural_net_set_theta (Neural_net *nn, double t_theta)
  554. {
  555.   nn->theta = t_theta;
  556. }
  557.  
  558. void Neural_net_set_phi (Neural_net *nn, double t_phi)
  559. {
  560.   nn->phi = t_phi;
  561. }
  562.  
  563. void Neural_net_set_K (Neural_net *nn, double t_K)
  564. {
  565.   nn->K = t_K;
  566. }
  567.  
  568. double Neural_net_get_epsilon (Neural_net *nn)
  569. {
  570.   return (nn->epsilon);
  571. }
  572.  
  573. double Neural_net_get_skip_epsilon (Neural_net *nn)
  574. {
  575.   return (nn->skip_epsilon);
  576. }
  577.  
  578. double Neural_net_get_learning_rate (Neural_net *nn)
  579. {
  580.   return (nn->learning_rate);
  581. }
  582.  
  583. double Neural_net_get_theta (Neural_net *nn)
  584. {
  585.   return (nn->theta);
  586. }
  587.  
  588. double Neural_net_get_phi (Neural_net *nn)
  589. {
  590.   return (nn->phi);
  591. }
  592.  
  593. double Neural_net_get_K (Neural_net *nn)
  594. {
  595.   return (nn->K);
  596. }
  597.  
  598. long   Neural_net_get_iterations (Neural_net *nn)
  599. {
  600.   return (nn->training_examples);
  601. }
  602.  
  603. #endif
  604.  
  605. void Neural_net_back_propagation (Neural_net *nn, double *input,
  606.                                   double *desired_output, int *done)
  607. {
  608.   int     x,y;
  609.   register int size;
  610.   double  delta,sum_delta,*weight,*p_sum_delta,*p_learning_delta;
  611.  
  612.   /* First check if training complete. */
  613.   for (x = nn->num_outputs - 1; x >= 0; --x)
  614.     {
  615.       if ( fabs (desired_output [x] - nn->output_act [x]) > 0.1 )
  616.         {
  617.           *done = 0;
  618.         }
  619.     }
  620.  
  621.   /* Go backward through list for speed */
  622.   size = nn->num_hidden2;
  623.   /* First calculate deltas of weights from output to hidden layer 2. */
  624.   for (x = nn->num_outputs - 1; x >= 0; --x)
  625.     {
  626.       weight = &nn->hidden2_weights [x * size];
  627.       p_sum_delta = &nn->hidden2_weights_sum_delta [x * size];
  628.       p_learning_delta = &nn->hidden2_learning_delta [x * size];
  629.       for (y = nn->num_hidden2 - 1; y >= 0; --y)
  630.         {
  631.           /* Formula delta = (desired - actual) * derivative
  632.              derivative = S(1 - S)
  633.              Also calculate sum of deltas * weight for next layer.
  634.           */
  635.           delta = (desired_output [x] - nn->output_act [x])
  636.                    * SLOPE * nn->output_act [x] * (1.0 - nn->output_act [x]);
  637.  
  638.           nn->hidden2_sum_delta_weight [y] += delta * weight [y];
  639.  
  640.           p_learning_delta [y] += delta;
  641.  
  642.           /* Now multiply by activation and sum in weights sum delta */
  643.           p_sum_delta [y] += delta * nn->hidden2_act [y];
  644.         }
  645.     }
  646.  
  647.  
  648.   /* Next calculate deltas of weights between hidden layer2 and hidden
  649.      layer 1 */
  650.   size = nn->num_hidden1;
  651.   for (x = nn->num_hidden2 - 1; x >= 0; --x)
  652.     {
  653.       sum_delta = nn->hidden2_sum_delta_weight [x];
  654.       weight = &nn->hidden1_weights [x * size];
  655.       p_sum_delta = &nn->hidden1_weights_sum_delta [x * size];
  656.       p_learning_delta = &nn->hidden1_learning_delta [x * size];
  657.       for (y = nn->num_hidden1 - 1; y >= 0; --y)
  658.         {
  659.           /* Formula delta = SUM (previous deltas*weight)
  660.                              * derivative
  661.              previous deltas already muliplied by weight.
  662.              derivative = S(1 - S)
  663.  
  664.              Also calculate sum of deltas * weight to save from doing
  665.              it for next layer.
  666.           */
  667.  
  668.           delta = sum_delta * nn->hidden2_act [x] *
  669.                   (1.0 - nn->hidden2_act [x]) * SLOPE;
  670.  
  671.           nn->hidden1_sum_delta_weight [y] += delta * weight [y];
  672.  
  673.           p_learning_delta [y] += delta;
  674.  
  675.           /* Now multiply by activation and sum in weights_sum_delta */
  676.           p_sum_delta [y] += delta * nn->hidden1_act [y];
  677.         }
  678.       nn->hidden2_sum_delta_weight [x] = 0.0;
  679.     }
  680.  
  681.   /* Finally calculate deltas of weights between hidden layer 1 and input
  682.      layer */
  683.   size = nn->num_inputs;
  684.   for (x = nn->num_hidden1 - 1; x >= 0; --x)
  685.     {
  686.       sum_delta = nn->hidden1_sum_delta_weight [x];
  687.       p_sum_delta = &nn->input_weights_sum_delta [x * size];
  688.       p_learning_delta = &nn->input_learning_delta [x * size];
  689.       for (y = nn->num_inputs - 1; y >= 0; --y)
  690.         {
  691.           /* Formula delta = SUM (previous deltas*weight)
  692.                              * derivative * activation of input
  693.              previous deltas already muliplied by weight
  694.              derivative = S(1 - S)
  695.           */
  696.           delta = sum_delta * nn->hidden1_act [x] *
  697.                   (1.0 - nn->hidden1_act [x]) * SLOPE;
  698.  
  699.           p_learning_delta [y] += delta;
  700.  
  701.           p_sum_delta [y] += (delta * input [y]);
  702.         }
  703.       nn->hidden1_sum_delta_weight [x] = 0.0;
  704.     }
  705.  
  706.   /* Now all deltas have been calculated and added into their appropriate
  707.      neuron connection. */
  708.   ++nn->examples_since_update;
  709.  
  710. }
  711.  
  712.  
  713. double Neural_net_calc_forward (Neural_net *nn, double *input,
  714.                                 double *desired_output, int *num_wrong,
  715.                                 int *skip, int print_it, int *actual_printed)
  716. {
  717.   int     x,y,wrong;
  718.   int     size;
  719.   double  *weight,error,abs_error;
  720.  
  721.   *skip = 1;
  722.   wrong = 0;
  723.   error = 0.0;
  724.  
  725.   /* Go backward for faster processing */
  726.   /* Calculate hidden layer 1's activation */
  727.   size = nn->num_inputs;
  728.   for (x = nn->num_hidden1 - 1; x >= 0;  --x)
  729.     {
  730.       nn->hidden1_act [x] = 0.0;
  731.       weight = &nn->input_weights [x * size];
  732.       for (y = nn->num_inputs - 1; y >= 0; --y)
  733.         {
  734.           nn->hidden1_act [x] += (input [y] * weight [y]);
  735.         }
  736.       nn->hidden1_act [x] = S(nn->hidden1_act [x]);
  737.     }
  738.  
  739.   /* Calculate hidden layer 2's activation */
  740.   size = nn->num_hidden1;
  741.   for (x = nn->num_hidden2 - 1; x >= 0; --x)
  742.     {
  743.       nn->hidden2_act [x] = 0.0;
  744.       weight = &nn->hidden1_weights [x * size];
  745.       for (y = nn->num_hidden1 - 1; y >= 0; --y)
  746.         {
  747.           nn->hidden2_act [x] += (nn->hidden1_act [y] * weight [y]);
  748.         }
  749.       nn->hidden2_act [x] = S(nn->hidden2_act [x]);
  750.     }
  751.  
  752.   /* Calculate output layer's activation */
  753.   size = nn->num_hidden2;
  754.   for (x = nn->num_outputs - 1; x >= 0; --x)
  755.     {
  756.       nn->output_act [x] = 0.0;
  757.       weight = &nn->hidden2_weights [x * size];
  758.       for (y = nn->num_hidden2 - 1; y >= 0; --y)
  759.         {
  760.           nn->output_act [x] += nn->hidden2_act [y] * weight [y];
  761.         }
  762.       nn->output_act [x] = S(nn->output_act [x]);
  763.       abs_error = fabs (nn->output_act [x] - desired_output [x]);
  764.       error += abs_error;
  765.       if ( abs_error > 0.1 )
  766.           wrong = 1;
  767.       if ( abs_error > nn->epsilon )
  768.           *skip = 0;
  769.     }
  770.  
  771.   if ( wrong )
  772.       ++(*num_wrong);
  773.  
  774.   if ( print_it == 2 )
  775.     {
  776.       for (x = 0; x < nn->num_outputs; ++x)
  777.         {
  778.           printf ("%6.4f ",nn->output_act [x]);
  779.         }
  780.       ++(*actual_printed);
  781.     }
  782.   else if ( print_it && wrong )
  783.     {
  784.       for (x = 0; x < nn->num_outputs; ++x)
  785.         {
  786.           printf ("%6.4f ",fabs (desired_output [x] - nn->output_act [x]));
  787.         }
  788.       ++(*actual_printed);
  789.     }
  790.  
  791.   return (error);
  792.  
  793. }
  794.  
  795.  
  796. void Neural_net_update_weights (Neural_net *nn)
  797. {
  798.   int     x,y;
  799.   int     size;
  800.   double  rate,*p_ldelta,*p_ldelta_bar,*weight,*p_lrate,*p_sum_delta;
  801.  
  802.   /* Check to see if any changes have been calculated. */
  803.   if ( nn->examples_since_update == 0 )
  804.     {
  805.       return;
  806.     }
  807.  
  808.   /* Go backward for slightly faster processing */
  809.   /* First add deltas of weights from output to hidden layer 2. */
  810.   size = nn->num_hidden2;
  811.   for (x = nn->num_outputs - 1; x >= 0; --x)
  812.     {
  813.       p_ldelta = &nn->hidden2_learning_delta [x * size];
  814.       p_ldelta_bar = &nn->hidden2_learning_delta_bar [x * size];
  815.       weight = &nn->hidden2_weights [x * size];
  816.       p_lrate = &nn->hidden2_learning_rate [x * size];
  817.       p_sum_delta = &nn->hidden2_weights_sum_delta [x * size];
  818.  
  819.       for (y = nn->num_hidden2 - 1; y >= 0; --y)
  820.         {
  821.           rate = p_ldelta [y] * p_ldelta_bar [y];
  822.           if ( rate < 0.0 )
  823.             {
  824.               p_lrate [y] -= (nn->phi * p_lrate [y]);
  825.             }
  826.           else if ( rate > 0.0 )
  827.             {
  828.               p_lrate [y] += nn->K;
  829.             }
  830.  
  831.           weight [y] += (p_lrate [y] * p_sum_delta [y]);
  832.           p_sum_delta [y] = 0.0;
  833.           p_ldelta_bar [y] *= nn->theta;
  834.           p_ldelta_bar [y] += ((1.0 - nn->theta) * p_ldelta [y]);
  835.           p_ldelta [y] = 0.0;
  836.         }
  837.     }
  838.  
  839.   /* Next add deltas of weights between hidden layer2 and hidden
  840.      layer 1 */
  841.   size = nn->num_hidden1;
  842.   for (x = nn->num_hidden2 - 1; x >= 0; --x)
  843.     {
  844.       p_ldelta = &nn->hidden1_learning_delta [x * size];
  845.       p_ldelta_bar = &nn->hidden1_learning_delta_bar [x * size];
  846.       weight = &nn->hidden1_weights [x * size];
  847.       p_lrate = &nn->hidden1_learning_rate [x * size];
  848.       p_sum_delta = &nn->hidden1_weights_sum_delta [x * size];
  849.  
  850.       for (y = nn->num_hidden1 - 1; y >= 0; --y)
  851.         {
  852.           rate = p_ldelta [y] * p_ldelta_bar [y];
  853.           if ( rate < 0.0 )
  854.             {
  855.               p_lrate [y] -= (nn->phi * p_lrate [y]);
  856.             }
  857.           else if ( rate > 0.0 )
  858.             {
  859.               p_lrate [y] += nn->K;
  860.             }
  861.  
  862.           weight [y] += (p_lrate [y] * p_sum_delta [y]);
  863.           p_sum_delta [y] = 0.0;
  864.           p_ldelta_bar [y] *= nn->theta;
  865.           p_ldelta_bar [y] += ((1.0 - nn->theta) * p_ldelta [y]);
  866.           p_ldelta [y] = 0.0;
  867.         }
  868.     }
  869.  
  870.   /* Finally add deltas of weights between hidden layer 1 and input
  871.      layer */
  872.   size = nn->num_inputs;
  873.   for (x = nn->num_hidden1 - 1; x >= 0; --x)
  874.     {
  875.       p_ldelta = &nn->input_learning_delta [x * size];
  876.       p_ldelta_bar = &nn->input_learning_delta_bar [x * size];
  877.       weight = &nn->input_weights [x * size];
  878.       p_lrate = &nn->input_learning_rate [x * size];
  879.       p_sum_delta = &nn->input_weights_sum_delta [x * size];
  880.  
  881.       for (y = nn->num_inputs - 1; y >= 0; --y)
  882.         {
  883.           rate = p_ldelta [y] * p_ldelta_bar [y];
  884.           if ( rate < 0.0 )
  885.             {
  886.               p_lrate [y] -= (nn->phi * p_lrate [y]);
  887.             }
  888.           else if ( rate > 0.0 )
  889.             {
  890.               p_lrate [y] += nn->K;
  891.             }
  892.  
  893.           weight [y] += (p_lrate [y] * p_sum_delta [y]);
  894.           p_sum_delta [y] = 0.0;
  895.           p_ldelta_bar [y] *= nn->theta;
  896.           p_ldelta_bar [y] += ((1.0 - nn->theta) * p_ldelta [y]);
  897.           p_ldelta [y] = 0.0;
  898.         }
  899.     }
  900.  
  901.   /* Now all deltas have been added into their appropriate neuron
  902.      connection. */
  903.   nn->training_examples += nn->examples_since_update;
  904.   nn->examples_since_update = 0;
  905.  
  906. }
  907.  
  908.  
  909. int Neural_net_calc_forward_test (Neural_net *nn, double input [],
  910.                                   double desired_output [],
  911.                                   int print_it, double correct_eps,
  912.                                   double good_eps)
  913. {
  914.   int x,y,wrong,good;
  915.  
  916.   wrong = 0;
  917.   good = 0;
  918.  
  919.   /* Go backward for faster processing */
  920.   /* Calculate hidden layer 1's activation */
  921.   for (x = nn->num_hidden1 - 1; x >= 0;  --x)
  922.     {
  923.       nn->hidden1_act [x] = 0.0;
  924.       for (y = nn->num_inputs - 1; y >= 0; --y)
  925.         {
  926.           nn->hidden1_act [x] += (input [y] *
  927.                               nn->input_weights [x * nn->num_inputs + y]);
  928.         }
  929.       nn->hidden1_act [x] = S(nn->hidden1_act [x]);
  930.     }
  931.  
  932.   /* Calculate hidden layer 2's activation */
  933.   for (x = nn->num_hidden2 - 1; x >= 0; --x)
  934.     {
  935.       nn->hidden2_act [x] = 0.0;
  936.       for (y = nn->num_hidden1 - 1; y >= 0; --y)
  937.         {
  938.           nn->hidden2_act [x] += (nn->hidden1_act [y] *
  939.                                  nn->hidden1_weights [x*nn->num_hidden1 + y]);
  940.         }
  941.       nn->hidden2_act [x] = S(nn->hidden2_act [x]);
  942.     }
  943.  
  944.   /* Calculate output layer's activation */
  945.   for (x = nn->num_outputs - 1; x >= 0; --x)
  946.     {
  947.       nn->output_act [x] = 0.0;
  948.       for (y = nn->num_hidden2 - 1; y >= 0; --y)
  949.         {
  950.           nn->output_act [x] += nn->hidden2_act [y] *
  951.                                 nn->hidden2_weights [x * nn->num_hidden2 + y];
  952.         }
  953.       nn->output_act [x] = S(nn->output_act [x]);
  954.  
  955.       if ( fabs (nn->output_act [x] - desired_output [x]) > good_eps )
  956.           wrong = 1;
  957.       else if ( fabs (nn->output_act [x] - desired_output [x]) > correct_eps )
  958.           good = 1;
  959.     }
  960.  
  961.   if ( print_it )
  962.     {
  963.       for (x = 0; x < nn->num_outputs; ++x)
  964.         {
  965.           printf ("%6.4f ",nn->output_act [x]);
  966.         }
  967.     }
  968.  
  969.   if ( wrong )
  970.       return (WRONG);
  971.   else if ( good )
  972.       return (GOOD);
  973.   else
  974.       return (CORRECT);
  975. }
  976.  
  977.  
  978. void Neural_net_kick_weights (Neural_net *nn, double range)
  979. {
  980.   int    x;
  981.   double rand_max;
  982.   double variation;
  983.  
  984.   rand_max = RAND_MAX;
  985.   /* Add from -range to +range to all weights randomly */
  986.   for (x = 0; x < (nn->num_hidden1 * nn->num_inputs); ++x)
  987.     {
  988.       variation = rand () / rand_max * range;
  989.       if ( rand () < (RAND_MAX / 2) )
  990.           variation *= -1.0;
  991.       nn->input_weights [x] += variation;
  992.     }
  993.  
  994.   for (x = 0; x < (nn->num_hidden2 * nn->num_hidden1); ++x)
  995.     {
  996.       variation = rand () / rand_max * range;
  997.       if ( rand () < (RAND_MAX / 2) )
  998.           variation *= -1.0;
  999.       nn->hidden1_weights [x] += variation;
  1000.     }
  1001.  
  1002.   for (x = 0; x < (nn->num_outputs * nn->num_hidden2); ++x)
  1003.     {
  1004.       variation = rand () / rand_max * range;
  1005.       if ( rand () < (RAND_MAX / 2) )
  1006.           variation *= -1.0;
  1007.       nn->hidden2_weights [x] += variation;
  1008.     }
  1009.  
  1010. }
  1011.  
  1012.