Advertisement
drankinatty

Simple neural network implementation in C

Jan 5th, 2022
1,449
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.00 KB | None | 1 0
  1. /*
  2.  *  main.cpp
  3.  *  NeuralNetwork
  4.  *
  5.  *  Created by Santiago Becerra on 9/15/19.
  6.  *  Copyright © 2019 Santiago Becerra. All rights reserved.
  7.  *
  8.  *  Simple neural network implementation in C
  9.  *  https://towardsdatascience.com/simple-neural-network-implementation-in-c-663f51447547
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <math.h>
  15.  
  16. // Simple network that can learn XOR
  17. // Feartures : sigmoid activation function, stochastic gradient descent, and mean square error fuction
  18.  
  19. // Potential improvements :
  20. // Different activation functions
  21. // Batch training
  22. // Different error funnctions
  23. // Arbitrary number of hidden layers
  24. // Read training end test data from a file
  25. // Add visualization of training
  26. // Add recurrence? (maybe that should be a separate project)
  27.  
  28. double sigmoid(double x) { return 1 / (1 + exp(-x)); }
  29. double dSigmoid(double x) { return x * (1 - x); }
  30. double init_weight() { return ((double)rand())/((double)RAND_MAX); }
  31. void shuffle(int *array, size_t n)
  32. {
  33.     if (n > 1)
  34.     {
  35.         size_t i;
  36.         for (i = 0; i < n - 1; i++)
  37.         {
  38.             size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
  39.             int t = array[j];
  40.             array[j] = array[i];
  41.             array[i] = t;
  42.         }
  43.     }
  44. }
  45.  
  46. int main (void) {
  47.  
  48. #define numInputs 2
  49. #define numHiddenNodes 2
  50. #define numOutputs 1
  51.    
  52.     const double lr = 0.1f;
  53.    
  54.     double hiddenLayer[numHiddenNodes];
  55.     double outputLayer[numOutputs];
  56.    
  57.     double hiddenLayerBias[numHiddenNodes];
  58.     double outputLayerBias[numOutputs];
  59.  
  60.     double hiddenWeights[numInputs][numHiddenNodes];
  61.     double outputWeights[numHiddenNodes][numOutputs];
  62.    
  63. #define numTrainingSets 4
  64.  
  65.     double training_inputs[numTrainingSets][numInputs] = {{0.0f,0.0f},
  66.                                                           {1.0f,0.0f},
  67.                                                           {0.0f,1.0f},
  68.                                                           {1.0f,1.0f}};
  69.     double training_outputs[numTrainingSets][numOutputs] = {{0.0f},
  70.                                                             {1.0f},
  71.                                                             {1.0f},
  72.                                                             {0.0f}};
  73.    
  74.     for (int i=0; i<numInputs; i++) {
  75.         for (int j=0; j<numHiddenNodes; j++) {
  76.             hiddenWeights[i][j] = init_weight();
  77.         }
  78.     }
  79.     for (int i=0; i<numHiddenNodes; i++) {
  80.         hiddenLayerBias[i] = init_weight();
  81.         for (int j=0; j<numOutputs; j++) {
  82.             outputWeights[i][j] = init_weight();
  83.         }
  84.     }
  85.     for (int i=0; i<numOutputs; i++) {
  86.         outputLayerBias[i] = init_weight();
  87.     }
  88.    
  89.     int trainingSetOrder[] = {0,1,2,3};
  90.    
  91.     for (int n=0; n < 10000; n++) {
  92.         shuffle(trainingSetOrder,numTrainingSets);
  93.         for (int x=0; x<numTrainingSets; x++) {
  94.            
  95.             int i = trainingSetOrder[x];
  96.            
  97.             // Forward pass
  98.            
  99.             for (int j=0; j<numHiddenNodes; j++) {
  100.                 double activation=hiddenLayerBias[j];
  101.                  for (int k=0; k<numInputs; k++) {
  102.                     activation+=training_inputs[i][k]*hiddenWeights[k][j];
  103.                 }
  104.                 hiddenLayer[j] = sigmoid(activation);
  105.             }
  106.            
  107.             for (int j=0; j<numOutputs; j++) {
  108.                 double activation=outputLayerBias[j];
  109.                 for (int k=0; k<numHiddenNodes; k++) {
  110.                     activation+=hiddenLayer[k]*outputWeights[k][j];
  111.                 }
  112.                 outputLayer[j] = sigmoid(activation);
  113.             }
  114.            
  115.             printf ("Input:%lg %lg    Output:%lg    Expected Output: %lg\n",
  116.                     training_inputs[i][0], training_inputs[i][1],
  117.                     outputLayer[0], training_outputs[i][0]);
  118.                    
  119.            // Backprop
  120.            
  121.             double deltaOutput[numOutputs];
  122.             for (int j=0; j<numOutputs; j++) {
  123.                 double errorOutput = (training_outputs[i][j]-outputLayer[j]);
  124.                 deltaOutput[j] = errorOutput*dSigmoid(outputLayer[j]);
  125.             }
  126.            
  127.             double deltaHidden[numHiddenNodes];
  128.             for (int j=0; j<numHiddenNodes; j++) {
  129.                 double errorHidden = 0.0f;
  130.                 for(int k=0; k<numOutputs; k++) {
  131.                     errorHidden+=deltaOutput[k]*outputWeights[j][k];
  132.                 }
  133.                 deltaHidden[j] = errorHidden*dSigmoid(hiddenLayer[j]);
  134.             }
  135.            
  136.             for (int j=0; j<numOutputs; j++) {
  137.                 outputLayerBias[j] += deltaOutput[j]*lr;
  138.                 for (int k=0; k<numHiddenNodes; k++) {
  139.                     outputWeights[k][j]+=hiddenLayer[k]*deltaOutput[j]*lr;
  140.                 }
  141.             }
  142.            
  143.             for (int j=0; j<numHiddenNodes; j++) {
  144.                 hiddenLayerBias[j] += deltaHidden[j]*lr;
  145.                 for(int k=0; k<numInputs; k++) {
  146.                     hiddenWeights[k][j]+=training_inputs[i][k]*deltaHidden[j]*lr;
  147.                 }
  148.             }
  149.         }
  150.     }
  151.    
  152.     // Print weights
  153.     fputs ("Final Hidden Weights\n[ ", stdout);
  154.     for (int j=0; j<numHiddenNodes; j++) {
  155.         fputs ("[ ", stdout);
  156.         for(int k=0; k<numInputs; k++) {
  157.             printf ("%lf ", hiddenWeights[k][j]);
  158.         }
  159.         fputs ("] ", stdout);
  160.     }
  161.    
  162.     fputs ("]\nFinal Hidden Biases\n[ ", stdout);
  163.     for (int j=0; j<numHiddenNodes; j++) {
  164.         printf ("%lf ", hiddenLayerBias[j]);
  165.     }
  166.     fputs ("]\nFinal Output Weights", stdout);
  167.     for (int j=0; j<numOutputs; j++) {
  168.         fputs ("[ ", stdout);
  169.         for (int k=0; k<numHiddenNodes; k++) {
  170.             printf ("%lf ", outputWeights[k][j]);
  171.         }
  172.         fputs ("]\n", stdout);
  173.     }
  174.     fputs ("Final Output Biases\n[ ", stdout);
  175.     for (int j=0; j<numOutputs; j++) {
  176.         printf ("%lf ", outputLayerBias[j]);
  177.        
  178.     }
  179.     fputs ("]\n", stdout);
  180.  
  181.     return 0;
  182. }
  183.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement