Advertisement
bsddeamon

BPANN.c

Jul 23rd, 2016
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.83 KB | None | 0 0
  1. // BPANN.c
  2. // BackPropagation Artificial Neural Network.
  3. // Apprend n'importe quelle fonction booleenne
  4. // a 2 bits d'entree et 1 bit de sortie.
  5. // Hacker: Samuel Duclos
  6. #include <DS89C4xx.h>
  7. #include <stdio.h>
  8. #include <stdlib.h> // rand().
  9. #include <math.h> // exp(x) == e^x.
  10.  
  11. #define UC unsigned char
  12. #define USI unsigned short int
  13. #define XF float xdata
  14.  
  15. // Matrices a visibilite globale.
  16. // 3*4
  17. XF synapses0[3][4];
  18. XF inputT[3][4];
  19. XF sensitivity0D[3][4];
  20.  
  21. // 4*4
  22. XF sensitivity0[4][4];
  23. XF results1[4][4];
  24. XF results1T[4][4];
  25.  
  26. // 4*1
  27. XF synapses1[4][1];
  28. XF sensitivity1[4][1];
  29. XF output[4][1];
  30. XF results2[4][1];
  31. XF sensitivity1D[4][1];
  32.  
  33. // 4*3
  34. XF input[4][3];
  35.  
  36. // 1*4
  37. XF synapses1T[1][4];
  38.  
  39. // Inutile de lire les prototypes…
  40. void vInitPortSerie(void);
  41. UC select_input(void);
  42. void process_input(void);
  43. void rand_synapses(float **, UC, UC);
  44. void transpose(float **, float **, UC, UC);
  45. void connect(float **, float **, float **, UC, UC, UC);
  46. void detonate(float **, UC, UC);
  47. void feedforward(void);
  48. void feedback(void);
  49. void update(void);
  50. void print_layer(float **, UC, UC);
  51. void output_results(void);
  52.  
  53. void main(void) {
  54.   USI count;
  55.  
  56.   vInitPortSerie();
  57.  
  58.   while (1) {
  59.     process_input();
  60.  
  61.     // 60000 boucles d’apprentissage.
  62.     for (count = 0; count < 60000; count++) {
  63.       feedforward(); // Propage le signal.
  64.       feedback(); // Apprend de ses erreurs.
  65.       update(); // Update l'apprentissage du reseau.
  66.     }
  67.     output_results();
  68.     getkey(); // Fin!
  69.   }
  70. }
  71.  
  72.  
  73. // Initialisation du port serie.
  74. void vInitPortSerie(void) {
  75.   SCON0 = 0x50;
  76.   TMOD |= 0x20;
  77.   TH1 = 0xFF;
  78.   PCON = 0x80;
  79.   TR1 = 1;
  80.   TI_0 = 1;
  81. }
  82.  
  83. // Recoit 0 ou 1 du clavier.
  84. UC select_input(void) {
  85.   UC x;
  86.   do { x = getchar();
  87.   } while (x != '0' && x != '1');
  88.   return(x - '0');
  89. }
  90.  
  91. // Initialise les matrices selon les inputs/outputs choisis (3*4).
  92. // Exemple (XOR) :
  93. // 0 0 0
  94. // 0 1 1
  95. // 1 0 1
  96. // 1 1 0
  97. // Les synapses sont initialisees aleatoirement.
  98. void process_input(void) {
  99.   UC i;
  100.   rand_synapses(synapses0, 3, 4);
  101.   rand_synapses(synapses1, 4, 1);
  102.   printf("Enter 3*4 boolean table.\n");
  103.   printf("This will train a neural network to learn it.\n");
  104.   for (i = 0; i < 4; i++) {
  105.     printf("\n%bu: 2 inputs, 1 output (0 or 1) ", i);
  106.     input[i][0] = select_input();
  107.     input[i][1] = select_input();
  108.     input[i][2] = 1;
  109.     output[i][0] = select_input();
  110.   }
  111. }
  112.  
  113. // Initialise les neurones aleatoirement entre -1.0 et 1.0.
  114. void rand_synapses(float **synapses, UC m, UC n) {
  115.   UC i, j;
  116.   for (i = 0; i < m; i++) {
  117.     for (j = 0; j < n; j++) {
  118.       synapses[i][j] = ((float)(rand()%10))/5-1;
  119.     }
  120.   }
  121. }
  122.  
  123. // Echange les x (inputs) avec les y (outputs).
  124. void transpose(float **matrix, float **matrixT, UC m, UC n) {
  125.   UC i, j;
  126.   for (i = 0; i < m; i++) {
  127.     for (j = 0; j < n; j++) {
  128.       matrixT[j][i] = matrix[i][j];
  129.     }
  130.   }
  131. }
  132.  
  133. // Simule la loi d’Ohm (V = RI) sur deux matrices.
  134. // Les valeurs sont des courants (multiplies par des resistances).
  135. void connect(float **input_layer, float **output_layer, float **results, UC x1, UC y1, UC y2) {
  136.   unsigned char i, j, k;
  137.   for (i = 0; i < x1; i++) {
  138.     for (j = 0; j < y2; j++) {
  139.       results[i][j] = 0;
  140.       for (k = 0; k < y1; k++) {
  141.         results[i][j] += input_layer[i][k] * output_layer[k][j];
  142.       }
  143.     }
  144.   }
  145. }
  146.  
  147. // Simule la detonation du output (axone) des neurones.
  148. void detonate(float **neuron, UC m, UC n) {
  149.   UC i, j;
  150.   for (i = 0; i < m; i++) {
  151.     for (j = 0; j < n; j++) {
  152.       neuron[i][j] = 1/(1+exp(-neuron[i][j]));
  153.     }
  154.   }
  155. }
  156.  
  157. // Propagation des signaux d'entree sur les differentes
  158. // couches de neurones jusqu'a la sortie.
  159. void feedforward(void) {
  160.   connect(input, synapses0, results1, 4, 3, 4);
  161.   detonate(results1, 4, 4);
  162.   connect(results1, synapses1, results2, 4, 4, 1);
  163.   detonate(results2, 4, 1);
  164. }
  165.  
  166. // APPRENTISSAGE MACHINE
  167. // Retropropagation du signal (sortie vers entree)
  168. // en fonction de la sensibilite individuelle des neurones.
  169. void feedback(void) {
  170.   UC i, j;
  171.   for (i = 0; i < 4; i++) {
  172.     // output = feedforward()
  173.     // erreur = (reponse - output)
  174.     // sensibilite = (erreur * derivee_signal)
  175.     sensitivity1[i][0] = (output[i][0] - results2[i][0]) * results2[i][0] * (1 - results2[i][0]);
  176.   }
  177.   // Inverse le input avec le output.
  178.   transpose(synapses1, synapses1T, 4, 1);
  179.   // V = RI
  180.   connect(sensitivity1, synapses1T, sensitivity0, 4, 1, 4);
  181.   for (i = 0; i < 4; i++) {
  182.     for (j = 0; j < 4; j++) {
  183.       // sensibilite_input =
  184.       //   (sensibilite_input * derivee_output)
  185.       sensitivity0[i][j] *= results1[i][j] * (1 - results1[i][j]);
  186.     }
  187.   }
  188. }
  189.  
  190. // Ajuste les resistances synaptiques.
  191. void update(void) {
  192.   UC i, j;
  193.   // Inverse le sens du courant.
  194.   transpose(results1, results1T, 4, 4);
  195.   // Connecte les resultats a la sensibilite.
  196.   connect(results1T, sensitivity1, sensitivity1D, 4, 4, 1);
  197.   for (i = 0; i < 4; i++) {
  198.     for (j = 0; j < 1; j++) {
  199.       synapses1[i][0] += sensitivity1D[i][0];
  200.     }
  201.   }
  202.  
  203.   // Inverse le sens du courant.
  204.   transpose(input, inputT, 4, 3);
  205.   // Connecte les resultats a la sensibilite.
  206.   connect(inputT, sensitivity0, sensitivity0D, 3, 4, 4);
  207.   for (i = 0; i < 3; i++) {
  208.     for (j = 0; j < 4; j++) {
  209.       synapses0[i][j] += sensitivity0D[i][j];
  210.     }
  211.   }
  212. }
  213.  
  214. // Imprime une matrice a l'ecran.
  215. void print_layer(float **layer, UC m, UC n) {
  216.   UC i, j;
  217.   for (i = 0; i < m; i++) {
  218.     printf("\n");
  219.     for (j = 0; j < n; j++) {
  220.       printf("%5.4f ", layer[i][j]);
  221.     }
  222.   }
  223. }
  224.  
  225. // Imprime le dernier output du reseau, puis les valeurs synaptiques.
  226. void output_results(void) {
  227.   printf("\nForward pass results:\n");
  228.   print_layer(results2, 4, 1);
  229.   printf("\nSynapse layer 0:\n");
  230.   print_layer(synapses0, 3, 4);
  231.   printf("\nSynapse layer 1:\n");
  232.   print_layer(synapses1, 4, 1);
  233. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement