source: tag/release-8/yao8/product/include/Dynnet.h @ 1

Last change on this file since 1 was 1, checked in by lnalod, 15 years ago

Initial import of YAO sources

  • Property svn:eol-style set to native
File size: 18.9 KB
Line 
1
2/* ////////////////////////////////////////////////////////////////////////////
3//
4//              Ynet functions : allowed Yao to deal more or less with neural network
5//
6//////////////////////////////////////////////////////////////////////////// */
7
8
9/* ********************************* MACROS ***********************************
10//-------------------------------------------------------------------------- */
11#define poids(i,j) poids[3*i+j]
12
13double etats[YNMAXCELL] ;
14double gradients[YNMAXCELL];
15
16/* en raison de pbs avec le tableau dynamique input (dans Ynet_backward) */
17double input[YNMAXCELL] ;
18
19/* **************************** TYPES PRESONNALISES ***************************
20//-------------------------------------------------------------------------- */
21//typedef enum {SigLin, SigSig} Activation; /* -> Dynamo.h */
22
23/* ************************* PROTOTYPAGES DES FONCTIONS ***********************
24//-------------------------------------------------------------------------- */
25/* création d'une matrice des poids a partir d'un fichier SN */
26int Ynet_load (const int inet, char *fichier);
27
28/* fonctions utilisateur de propagation */
29void Ynet_forward (const int inet, const Activation activ, const double poids[],
30                 const int nbconnex, const YREAL etat_entree[], const int nbentree,
31                 YREAL etat_sortie[], const int nbsortie);
32               
33void Ynet_fward1(const int inet, const YREAL etat_entree[],YREAL etat_sortie[]);
34
35void Ynet_fward2(const int inet, YREAL etat_sortie[]);
36
37
38/* fonction utilisateur de retropropagation */
39void Ynet_backward (const int inet, const Activation activ, const double poids[],
40                 const int nbconnex,const YREAL grad_sortie[], const int nbsortie,
41                 const YREAL etat_entree[],YREAL grad_entree[], const int nbentree);
42               
43void Ynet_bward1(const int inet, YREAL grad_sortie[],
44                                                           const double etat_entree[],double grad_entree[]);
45               
46void Ynet_bward2(const int inet, YREAL grad_sortie[]);
47
48
49/* fonction pour le Lineaire Tangent (avec passe avant) */
50void Ynet_flinward (const int inet, Activation activ,
51                const double poids[], const int nbconnex,
52                const YREAL etat_entree[], const YREAL grad_entree[], const int nbentree,
53                YREAL etat_sortie[], YREAL grad_sortie[], const int nbsortie);
54               
55void Ynet_flward1(const int inet, YREAL etat_sortie[], YREAL grad_sortie[],
56                  const YREAL etat_entree[], YREAL grad_entree[]);
57
58void Ynet_flward2(const int inet, YREAL etat_sortie[], YREAL grad_sortie[]);
59
60
61/* fonctions d'activation employees et leurs derivees */
62double Ynet_sig  (const double x);      /* fonction sigmoide */
63double Ynet_dsig (const double x);      /* dérivée d'une fonction sigmoide */
64double Ynet_lin  (const double x);      /* fonction lineaire */
65double Ynet_dlin (const double x);  /* derivee d'une fonction lineaire */
66
67/* fonction utile: */
68/* indice maximum des neurones d'un tableau de poids */
69int Ynet_max_tab (const double poids[], const int nbconnex);
70
71
72/* ************************** VARIABLES GLOBALES ******************************
73//-------------------------------------------------------------------------- */
74// parametres d'une sigmoide (avec valeurs par defaut)
75double Yn_sig_mx                 = ((double)2)/((double)3); //mx1 ;
76double Yn_sig_dmin   = 0 ;
77double Yn_sig_scale  = 1/ tanh (((double) 2) / ((double) 3)); /* scale1 ; */
78double Yn_sig_offset = 0 ;
79/* parametres d'une fonction lineaire (avec valeurs par defaut) */
80double Yn_lin_dmin = 1 ;
81double Yn_lin_dmax = 1 ;
82double Yn_lin_th   = 1 ;
83
84
85/* ****************************** FONCTIONS ***********************************
86//-------------------------------------------------------------------------- */
87void Ynet_dispsig ()
88{                       /* affichage des parametres de la fonction sigmoide */
89                printf("sigmoid parameters : \n\tmx    =% -23.15e \n\tdmin  =% -23.15e \n\tscale =% -23.15e \n\toffset=% -23.15e\n",
90                                                Yn_sig_mx, Yn_sig_dmin, Yn_sig_scale, Yn_sig_offset);
91}
92//-------------------------------------------------------------------------- */
93void Ynet_displin ()
94{                       /* affichage des parametres de la fonction linear */
95                printf("linear parameters : \n\tdmin=% -23.15e \n\tdmax=% -23.15e \n\tth  =% -23.15e\n",
96                                                Yn_lin_dmin, Yn_lin_dmax,       Yn_lin_th);
97}
98//-------------------------------------------------------------------------- */
99void Ynet_setpsig (double mx, double dmin, double scale, double offset)
100{                       /* affectation des parametres de la fonction sigmoide */
101                Yn_sig_mx  = mx;
102                Yn_sig_dmin = dmin;
103                Yn_sig_scale = scale;
104                Yn_sig_offset = offset;
105}
106//-------------------------------------------------------------------------- */
107void Ynet_setplin (double dmin, double dmax, double th)
108{                       /* affectation des parametres de la fonction lineaire */
109                Yn_lin_dmin = dmin;
110                Yn_lin_dmax = dmax;
111                Yn_lin_th   = th;
112}
113
114/* ------------------------------------------------------------------------- */
115//int Ynet_load (int inet, char *fichier, double *&poids)
116int Ynet_load (int inet, char *fichier)
117{                       /* creation de la matrice des poids
118                        // in : . indice du reseau
119                        //                . nom du fichier contenant les poids (genere par SN)
120                        // out: . matrice des poids
121                        // return : nombre de connexions */
122
123        double *&poids = YTabNet[inet].tweight; /* pour faciliter la programmation */
124                                       
125        /* recherche du nombre de connexions */
126        int nbconnex;           /* nombre de connexions */
127        char cmd[BUFSIZE] = "wc -l ";           /* commande = wc -l fichier.wei */
128        strcat(cmd, fichier) ;
129        /* appel systeme et recuperation du resultat */
130        char buf[BUFSIZE];
131        FILE *ptr;
132        if ((ptr = popen(cmd, "r")) != NULL)
133                fgets(buf, BUFSIZE, ptr);
134        /* récuperation du nombre de lignes du fichier */
135        sscanf(buf,"%d",&nbconnex) ;   
136        nbconnex-- ;            /* nombre de connexions = nombre de lignes - 1 */
137               
138        poids = new double[nbconnex*3] ;        /* allocation du tableau des poids */
139        /*const int long_ligne = 30;           nb d'elts max par ligne */
140
141        ifstream f;                     /* fichie */
142        char *ligne ;           /* ligne parsee */
143        double val = 0; /* elt parse */ 
144        int ind = 0;            /* indice pour parcourir la matrice */
145       
146        /* allocation de l'espace pour une ligne parsee */
147        /*ligne = new char [long_ligne+1];   +1 pour le 0 terminal */
148        ligne = new char [BUFSIZE+1] ; /* +1 pour le 0 terminal */
149
150        f.open(fichier,ios::in); /* ouverture du fichier en lecture */
151        /* si echec a l'ouverture : message d'erreur */
152        if (f.fail()) cout << "erreur à l'ouverture" ;
153       
154        /*f.getline(ligne,long_ligne,'\n');    parcours de la ligne d'en-tete */
155        f.getline(ligne,BUFSIZE,'\n'); /* parcours de la ligne d'en-tete */
156        /* on repete */
157        /*do {  f.getline(ligne,long_ligne,' ');          parsage jusqu'a un espace */         
158        do {    f.getline(ligne,BUFSIZE,' ');   /* parsage jusqu'a un espace */         
159                                if (strcmp(ligne,"\0")) /* si la ligne lue n'est pas un espace */
160                                {               sscanf(ligne,"%le",&val); /* conversion en double */                                   
161                                        *(poids + ind++) = val ; /* mise dans la matrice et incrementation de l'indice */
162                                }
163                 }     
164        while (!f.eof()); /* jusqu'a la fin du fichier */
165       
166        delete ligne;           /* on libère la mémoire */
167       
168        /* On va chercher le numcell max lors du chargement des poids
169  plutot qu'a chaque appel des fct *ward !                */
170  int ind_max = Ynet_max_tab(poids, nbconnex); /* indice du dernier neurone de sortie */       
171  if (ind_max >= YNMAXCELL)
172  {     printf("Probem of size : required %d ; maximum %d\n",ind_max,YNMAXCELL) ;
173          exit(0) ;
174  }
175  /* et on le stock ainsi que le nombre de connexionx dans le tableau des reseaux */
176  YTabNet[inet].maxcell  = ind_max;
177  YTabNet[inet].nbweight = nbconnex;
178       
179        return nbconnex;        /* on retourne le nombre de connexions du réseau */
180}
181
182/* ------------------------------------------------------------------------- */
183int Ynet_max_tab (const double poids[], const int nbconnex)
184{                       /* indice maximum des neurones d'un tableau de poids   
185                        // in : matrice des poids et le nombre de poids
186                        // return : indice maximal des neurones references dans la matrice des poids */
187                               
188        double ind = poids[1];  /* variable tempo stockant l'indice maxi,
189                                                                                                        // initialise au premier indice rencontre */   
190        int x = 0;      /* variables de boucle */
191       
192        /* parcours de la matrice des poids */
193        for (x = 1; x < nbconnex ; x++)         
194                if (poids(x,1) > ind)/* si l'indice rencontre est superieur a la variable temporaire */                 
195                        ind = poids(x,1);  /* on met a jour la variable temporaire */
196       
197        return (int) ind; /* on retourne la valeur */
198}
199
200/* ------------------------------------------------------------------------- */
201double Ynet_sig (const double x)
202{               /* fonction sigmoide
203                // in : parametres (en global) de la sigmoide et le point x
204                // return : sig(x) = scale * tanh (mx * x)+ offset + dmin * x                                    */
205
206          return (Yn_sig_scale * tanh (Yn_sig_mx * x) + Yn_sig_offset + Yn_sig_dmin * x);
207}
208
209/* ------------------------------------------------------------------------- */
210double Ynet_dsig (const double x)
211{               /* derivee d'une fonction sigmoide
212                // in : parametres (en global) de la sigmoide et le point x
213                // return : derivee de sig en x                                                                                                                                                                  */
214
215          return (Yn_sig_scale * Yn_sig_mx * (1 - tanh (Yn_sig_mx * x) *
216                              tanh (Yn_sig_mx * x)) + Yn_sig_dmin);
217}
218
219/* ------------------------------------------------------------------------- */
220double Ynet_lin (const double x)
221{               /* fonction lineaire (generalisee)
222                // in : parametres de la fonction lineaire generalisee et le point
223                // PRE : th >= 0
224                // return : lin(x) =
225                //              dmin * x - (dmax - dmin) * th   si x <= - th
226                //              dmax * x                        si -th <= x <= th
227                //              dmin * x + (dmax - dmin) * th   si x >= th                                                                                                       */
228                       
229        double fx; /* variable locale stockant f(x) */
230       
231        /* calcul de fx en fonction de la valeur de x */
232        if (x < -Yn_lin_th)
233                fx = Yn_lin_dmin * x - (Yn_lin_dmax - Yn_lin_dmin) * Yn_lin_th ;
234        else
235                if (x > Yn_lin_th)
236                        fx = Yn_lin_dmin * x + (Yn_lin_dmax - Yn_lin_dmin) * Yn_lin_th ;
237                else
238                        fx = Yn_lin_dmax * x ;
239                       
240        /* on retourne le resultat */
241        return fx ;
242}
243
244/* ------------------------------------------------------------------------- */
245double Ynet_dlin (const double x)
246{               /* derivee d'une fonction linéaire (generalisee)
247                // in : parametres (en global) de la fonction lineaire generalisee et le point x
248                // return : dérivée de lin en x
249                // CONVENTION : pour les points de discontinuité,
250                //              on prend comme derivee la moyenne
251                //              des derivees a gauche et a droite                                                                                                                                */
252                       
253        double dfx = 0; /* variable locale stockant df(x) */
254       
255        /* calcul de dfx en fonction de la valeur de x */
256        if (x < -Yn_lin_th || x > Yn_lin_th)
257                dfx = Yn_lin_dmin ;
258        else
259                if (x > -Yn_lin_th && x < Yn_lin_th)
260                        dfx = Yn_lin_dmax ;
261                else
262                        dfx = (Yn_lin_dmax + Yn_lin_dmin) / 2 ;
263                       
264        /* on retourne le resultat */
265        return dfx ;
266}
267
268
269/* ------------------------------------------------------------------------- */
270void Ynet_fward1(const int inet, const YREAL etat_entree[],YREAL etat_sortie[])
271{       Ynet_forward(inet, YTabNet[inet].activ,YTabNet[inet].tweight,YTabNet[inet].nbweight,etat_entree,
272                                                         YTabNet[inet].nbinput,etat_sortie,YTabNet[inet].nboutput);
273}
274void Ynet_fward2(const int inet, YREAL etat_sortie[])
275{       Ynet_forward(inet, YTabNet[inet].activ,YTabNet[inet].tweight,YTabNet[inet].nbweight,Yting,
276                                                         YTabNet[inet].nbinput,etat_sortie,YTabNet[inet].nboutput);
277}
278/* ------------------------------------------------------------------------- */
279void Ynet_forward (const int inet, Activation activ,
280                const double poids[], const int nbconnex,
281                const YREAL etat_entree[], const int nbentree,
282                YREAL etat_sortie[], const int nbsortie)
283{               /* fonction de propagation pour l'utilisateur
284                // in : indice du reseau, activation (type defini), matrice des poids,
285                //          nb de poids, tableau des etats des entrees, nombre d'entrees,
286                //          nombre de sorties
287                // out: tableau des etats des sorties                                                                                                                                    */
288
289        int ind_max = YTabNet[inet].maxcell; /* indice du dernier neurone de sortie */
290
291        int sortie1 = ind_max - nbsortie + 1;   /* indice du premier neurone de sortie */
292        int x = 0 ; /* variable de boucles */
293        int pre_crt = -1 ; /* neurone présynaptique courant */
294        int pre_new ; /* neurone présynaptique nouveau */
295
296        etats[0] = 1; /* biais = 1 */
297
298        /* insertion des entrees voulues */
299        for (x=0 ; x<nbentree ; x++)
300                etats[x+1] = etat_entree[x];
301
302        /* initialisation : */
303        for (x=nbentree+1 ; x <= ind_max ; x++)
304                etats[x] = 0 ;
305
306        /* propagation */
307        for (x=0 ; x<nbconnex ; x++)
308        {       pre_new = (int)poids(x,0) ;
309                if (pre_new != pre_crt)
310                {       pre_crt = pre_new ;
311                        if (pre_crt > nbentree && pre_crt < sortie1)
312                                etats[pre_crt] = Ynet_sig(etats[pre_crt]) ;
313                }
314                etats[(int)poids(x,1)] += etats[pre_new] * poids(x,2);
315        }
316
317        /* pour chaque neurone de la couche de sortie */
318        switch (activ)
319        {       case SigSig :
320                        for (x=sortie1 ; x<=ind_max ; x++)
321                                etats[x] = Ynet_sig(etats[x]) ;
322                        break ;
323                case SigLin :
324                        for (x=sortie1 ; x<=ind_max ; x++)
325                                etats[x] = Ynet_lin(etats[x]) ;
326                        break ;
327        }
328
329        /* for (x=0 ; x <= ind_max ; x++) printf("neurone %d : état %e\n",x,etats[x]) ; */
330
331        /* valeurs de retour */
332        for (x = 0 ; x < nbsortie ; x++)
333        {       etat_sortie[x] = etats[ind_max-nbsortie+1+x];
334                /* printf("sortie %d : ->%e<-\n",x,etat_sortie[x]); */
335        }
336}
337
338/* ------------------------------------------------------------------------- */
339void Ynet_bward1(const int inet, YREAL grad_sortie[], const YREAL etat_entree[], YREAL grad_entree[])
340{                Ynet_backward(inet, YTabNet[inet].activ,YTabNet[inet].tweight,YTabNet[inet].nbweight,
341                       grad_sortie, YTabNet[inet].nboutput,etat_entree,grad_entree,YTabNet[inet].nbinput);
342}
343void Ynet_bward2(const int inet, YREAL grad_sortie[])
344{                Ynet_backward(inet, YTabNet[inet].activ,YTabNet[inet].tweight,YTabNet[inet].nbweight,
345                       grad_sortie, YTabNet[inet].nboutput,Yting,Ytbeta,YTabNet[inet].nbinput);
346}
347/* ------------------------------------------------------------------------- */
348void Ynet_backward (const int inet, Activation activ,
349                const double poids[], const int nbconnex,
350                const YREAL grad_sortie[], const int nbsortie,
351                const YREAL etat_entree[],
352                YREAL grad_entree[], const int nbentree)
353{               /* fonction de retropropagation pour l'utilisateur
354                // in : indice du reseau, activation (type défini), matrice des poids,
355                //          nb de poids,tableau des gradients de sortie, nb de sorties,
356                //          tableau des états d'entree, nb d'entrees
357                // out: tableau des gradients d'entree                                                                                                                                   */
358
359        int ind_max = YTabNet[inet].maxcell;  /* indice du dernier neurone de sortie */
360
361        int sortie1 = ind_max - nbsortie + 1;   /* indice du premier neurone de sortie */
362        int x = 0 ; /* variable de boucles */
363        int pre_crt = -1 ; /* neurone présynaptique courant */
364        int pre_new ; /* neurone présynaptique nouveau */
365
366        etats[0] = 1; // biais = 1 */
367
368        /* insertion des entrees voulues */
369        for (x=0 ; x<nbentree ; x++)
370                  etats[x+1] = etat_entree[x];
371
372        /* initialisation : */
373        for (x=nbentree+1 ; x <= ind_max ; x++)
374                  etats[x] = 0 ;
375
376        /* propagation */
377        for (x=0 ; x<nbconnex ; x++)
378        {         pre_new = (int)poids(x,0) ;
379                  if (pre_new != pre_crt)
380                  {      pre_crt = pre_new ;
381                           if (pre_crt > nbentree && pre_crt < sortie1)
382                           {  input[pre_crt] = etats[pre_crt] ;
383                                  etats[pre_crt] = Ynet_sig(etats[pre_crt]) ;
384                           }
385                  }
386                  etats[(int)poids(x,1)] += etats[pre_new] * poids(x,2) ;
387        }
388
389        /* pour chaque neurone de la couche de sortie */
390        switch (activ)
391        {       case SigSig :
392                        for (x=sortie1 ; x<=ind_max ; x++)
393                        {         input[x] = etats[x] ;
394                                  etats[x] = Ynet_sig(etats[x]) ;
395                        }
396                        break ;
397                case SigLin :
398                        for (x=sortie1 ; x<=ind_max ; x++)
399                        {         input[x] = etats[x] ;
400                                  etats[x] = Ynet_lin(etats[x]) ;
401                        }
402                        break ;
403        }
404       
405        pre_crt = sortie1 - 1 ;
406
407        /* initialisation : */
408        for (x=0 ; x < sortie1 ; x++)
409                gradients[x] = 0 ;
410
411        /* insertion des gradients de sorties voulues */
412        switch (activ)
413        {       case SigSig :
414                        for (x = ind_max ; x >= sortie1 ;  x--)
415                                  gradients[x] = Ynet_dsig(input[x]) * grad_sortie[x-sortie1];
416                        break ;
417                case SigLin :
418                        for (x = ind_max ; x >= sortie1 ;  x--)
419                                  gradients[x] = Ynet_dlin(input[x]) * grad_sortie[x-sortie1] ;
420                        break ;
421        }
422
423        /* répropagation */
424        for (x=nbconnex-1 ; x>=0 ; x--)
425        {       pre_new = (int)poids(x,0) ;
426
427                if (pre_new != pre_crt)
428                {       if (pre_crt > nbentree && pre_crt < sortie1)
429                                gradients[pre_crt] *= Ynet_dsig(input[pre_crt]) ;
430                        pre_crt = pre_new ;
431                }
432                gradients[pre_new] += gradients[(int)poids(x,1)] * poids(x,2) ;
433        }
434
435        /* remplissage du poids des gradients d'entree */
436        for (x = 0 ; x < nbentree ; x++)
437                        grad_entree[x] = gradients[x+1];                                                            //bg+                                                       
438                        //grad_entree[x] = Ynet_dsig(0)*gradients[x+1];         //bg-
439
440        /* delete[] input;   free(input); */
441}
442
443/* ------------------------------------------------------------------------- */
444void Ynet_flward1(const int inet, YREAL etat_sortie[], YREAL grad_sortie[],
445                 const YREAL etat_entree[], YREAL grad_entree[])
446{    Ynet_flinward(inet, YTabNet[inet].activ,
447     YTabNet[inet].tweight,YTabNet[inet].nbweight,
448           etat_entree, grad_entree, YTabNet[inet].nbinput,
449           etat_sortie, grad_sortie,  YTabNet[inet].nboutput);
450
451}
452void Ynet_flward2(const int inet, YREAL etat_sortie[], YREAL grad_sortie[])
453{          Ynet_flinward(inet, YTabNet[inet].activ,
454     YTabNet[inet].tweight,YTabNet[inet].nbweight,
455           Yting, Ytbeta, YTabNet[inet].nbinput,
456           etat_sortie, grad_sortie,  YTabNet[inet].nboutput);
457}
458/* ------------------------------------------------------------------------- */
459void Ynet_flinward (const int inet, Activation activ,
460                const double poids[], const int nbconnex,
461                const YREAL etat_entree[], const YREAL grad_entree[], const int nbentree,
462                YREAL etat_sortie[], YREAL grad_sortie[], const int nbsortie)
463{
464        int ind_max = YTabNet[inet].maxcell;
465        int sortie1 = ind_max - nbsortie + 1;   /* indice du premier neurone de sortie */
466        int x = 0 ; /* variable de boucles */
467        int pre_crt = -1 ; /* neurone présynaptique courant */
468        int pre_new ; /* neurone présynaptique nouveau */
469
470        etats[0]     = 1;  /* biais = 1 */
471        gradients[0] = 0;  /* en passe avant, le gradient du biais = 0 !*/
472       
473        /* insertion des entrees (etats et gradients) */
474        for (x=0 ; x<nbentree ; x++)
475        {         etats[x+1] = etat_entree[x];
476                  gradients[x+1] = grad_entree[x];                                                        //bg+
477                  //gradients[x+1] = Ynet_dsig(0)*grad_entree[x];       //bg-
478        }
479
480        /* initialisation */
481        for (x=nbentree+1 ; x <= ind_max ; x++)
482        {         etats[x] = 0; gradients[x] = 0;}
483
484        /* propagation des etats et de leurs derivees sur les couches cachees */
485        for (x=0 ; x<nbconnex ; x++)
486        {         pre_new = (int)poids(x,0);
487                  if (pre_new != pre_crt)
488                  {      pre_crt = pre_new;
489                           if (pre_crt > nbentree && pre_crt < sortie1)
490                           {    gradients[pre_crt] *= Ynet_dsig(etats[pre_crt]);
491                              etats[pre_crt] = Ynet_sig(etats[pre_crt]);               
492                           }
493                  }
494                  etats[(int)poids(x,1)] += etats[pre_new] * poids(x,2) ;
495                  gradients[(int)poids(x,1)] += gradients[pre_new] * poids(x,2);
496        }
497
498        /* puis pour chaque neurone de la couche de sortie */
499        switch (activ)
500        {       case SigSig :
501                        for (x=sortie1 ; x<=ind_max ; x++)
502                        {         gradients[x] *= Ynet_dsig(etats[x]);
503                            etats[x] = Ynet_sig(etats[x]);
504                        }
505                        break ;
506                case SigLin :
507                        for (x=sortie1 ; x<=ind_max ; x++)
508                        {         gradients[x] *= Ynet_dlin(etats[x]);
509                            etats[x] = Ynet_lin(etats[x]);
510                        }
511                        break ;
512        }
513
514        /* remplissage des etats et gradients en sortie */
515        for (x=ind_max; x>=sortie1; --x)
516        {         grad_sortie[x-sortie1] = gradients[x];
517                        etat_sortie[x-sortie1] = etats[x];
518  }             
519}
520/* ========================================================================= */
521
Note: See TracBrowser for help on using the repository browser.