Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // BPANN.c
- // BackPropagation Artificial Neural Network.
- // Apprend n'importe quelle fonction booleenne
- // a 2 bits d'entree et 1 bit de sortie.
- // Hacker: Samuel Duclos
- #include <DS89C4xx.h>
- #include <stdio.h>
- #include <stdlib.h> // rand().
- #include <math.h> // exp(x) == e^x.
- #define UC unsigned char
- #define USI unsigned short int
- #define XF float xdata
- // Matrices a visibilite globale.
- // 3*4
- XF synapses0[3][4];
- XF inputT[3][4];
- XF sensitivity0D[3][4];
- // 4*4
- XF sensitivity0[4][4];
- XF results1[4][4];
- XF results1T[4][4];
- // 4*1
- XF synapses1[4][1];
- XF sensitivity1[4][1];
- XF output[4][1];
- XF results2[4][1];
- XF sensitivity1D[4][1];
- // 4*3
- XF input[4][3];
- // 1*4
- XF synapses1T[1][4];
- // Inutile de lire les prototypes…
- void vInitPortSerie(void);
- UC select_input(void);
- void process_input(void);
- void rand_synapses(float **, UC, UC);
- void transpose(float **, float **, UC, UC);
- void connect(float **, float **, float **, UC, UC, UC);
- void detonate(float **, UC, UC);
- void feedforward(void);
- void feedback(void);
- void update(void);
- void print_layer(float **, UC, UC);
- void output_results(void);
- void main(void) {
- USI count;
- vInitPortSerie();
- while (1) {
- process_input();
- // 60000 boucles d’apprentissage.
- for (count = 0; count < 60000; count++) {
- feedforward(); // Propage le signal.
- feedback(); // Apprend de ses erreurs.
- update(); // Update l'apprentissage du reseau.
- }
- output_results();
- getkey(); // Fin!
- }
- }
- // Initialisation du port serie.
- void vInitPortSerie(void) {
- SCON0 = 0x50;
- TMOD |= 0x20;
- TH1 = 0xFF;
- PCON = 0x80;
- TR1 = 1;
- TI_0 = 1;
- }
- // Recoit 0 ou 1 du clavier.
- UC select_input(void) {
- UC x;
- do { x = getchar();
- } while (x != '0' && x != '1');
- return(x - '0');
- }
- // Initialise les matrices selon les inputs/outputs choisis (3*4).
- // Exemple (XOR) :
- // 0 0 0
- // 0 1 1
- // 1 0 1
- // 1 1 0
- // Les synapses sont initialisees aleatoirement.
- void process_input(void) {
- UC i;
- rand_synapses(synapses0, 3, 4);
- rand_synapses(synapses1, 4, 1);
- printf("Enter 3*4 boolean table.\n");
- printf("This will train a neural network to learn it.\n");
- for (i = 0; i < 4; i++) {
- printf("\n%bu: 2 inputs, 1 output (0 or 1) ", i);
- input[i][0] = select_input();
- input[i][1] = select_input();
- input[i][2] = 1;
- output[i][0] = select_input();
- }
- }
- // Initialise les neurones aleatoirement entre -1.0 et 1.0.
- void rand_synapses(float **synapses, UC m, UC n) {
- UC i, j;
- for (i = 0; i < m; i++) {
- for (j = 0; j < n; j++) {
- synapses[i][j] = ((float)(rand()%10))/5-1;
- }
- }
- }
- // Echange les x (inputs) avec les y (outputs).
- void transpose(float **matrix, float **matrixT, UC m, UC n) {
- UC i, j;
- for (i = 0; i < m; i++) {
- for (j = 0; j < n; j++) {
- matrixT[j][i] = matrix[i][j];
- }
- }
- }
- // Simule la loi d’Ohm (V = RI) sur deux matrices.
- // Les valeurs sont des courants (multiplies par des resistances).
- void connect(float **input_layer, float **output_layer, float **results, UC x1, UC y1, UC y2) {
- unsigned char i, j, k;
- for (i = 0; i < x1; i++) {
- for (j = 0; j < y2; j++) {
- results[i][j] = 0;
- for (k = 0; k < y1; k++) {
- results[i][j] += input_layer[i][k] * output_layer[k][j];
- }
- }
- }
- }
- // Simule la detonation du output (axone) des neurones.
- void detonate(float **neuron, UC m, UC n) {
- UC i, j;
- for (i = 0; i < m; i++) {
- for (j = 0; j < n; j++) {
- neuron[i][j] = 1/(1+exp(-neuron[i][j]));
- }
- }
- }
- // Propagation des signaux d'entree sur les differentes
- // couches de neurones jusqu'a la sortie.
- void feedforward(void) {
- connect(input, synapses0, results1, 4, 3, 4);
- detonate(results1, 4, 4);
- connect(results1, synapses1, results2, 4, 4, 1);
- detonate(results2, 4, 1);
- }
- // APPRENTISSAGE MACHINE
- // Retropropagation du signal (sortie vers entree)
- // en fonction de la sensibilite individuelle des neurones.
- void feedback(void) {
- UC i, j;
- for (i = 0; i < 4; i++) {
- // output = feedforward()
- // erreur = (reponse - output)
- // sensibilite = (erreur * derivee_signal)
- sensitivity1[i][0] = (output[i][0] - results2[i][0]) * results2[i][0] * (1 - results2[i][0]);
- }
- // Inverse le input avec le output.
- transpose(synapses1, synapses1T, 4, 1);
- // V = RI
- connect(sensitivity1, synapses1T, sensitivity0, 4, 1, 4);
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
- // sensibilite_input =
- // (sensibilite_input * derivee_output)
- sensitivity0[i][j] *= results1[i][j] * (1 - results1[i][j]);
- }
- }
- }
- // Ajuste les resistances synaptiques.
- void update(void) {
- UC i, j;
- // Inverse le sens du courant.
- transpose(results1, results1T, 4, 4);
- // Connecte les resultats a la sensibilite.
- connect(results1T, sensitivity1, sensitivity1D, 4, 4, 1);
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 1; j++) {
- synapses1[i][0] += sensitivity1D[i][0];
- }
- }
- // Inverse le sens du courant.
- transpose(input, inputT, 4, 3);
- // Connecte les resultats a la sensibilite.
- connect(inputT, sensitivity0, sensitivity0D, 3, 4, 4);
- for (i = 0; i < 3; i++) {
- for (j = 0; j < 4; j++) {
- synapses0[i][j] += sensitivity0D[i][j];
- }
- }
- }
- // Imprime une matrice a l'ecran.
- void print_layer(float **layer, UC m, UC n) {
- UC i, j;
- for (i = 0; i < m; i++) {
- printf("\n");
- for (j = 0; j < n; j++) {
- printf("%5.4f ", layer[i][j]);
- }
- }
- }
- // Imprime le dernier output du reseau, puis les valeurs synaptiques.
- void output_results(void) {
- printf("\nForward pass results:\n");
- print_layer(results2, 4, 1);
- printf("\nSynapse layer 0:\n");
- print_layer(synapses0, 3, 4);
- printf("\nSynapse layer 1:\n");
- print_layer(synapses1, 4, 1);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement