Sunteți pe pagina 1din 7

L4 - Reţele neuronale feed forward, cu două straturi ascunse

LUCRARE DE LABORATOR NR. 4

REŢELE NEURONALE FEED FORWARD, CU DOUĂ STRATURI ASCUNSE

1. SCOPUL LUCRARII
In aceasta lucrare se studiaza o aplicatie practica a retelelor neuronale feed
forward cu doua straturi ascunse si anume se ilustreaza capacitatea retelelor neuronale
de a aproxima o functie cunoscuta intr-un numar discret de puncte.

2.BREVIAR TEORETIC
Intr-o retea feed forward neuronii sunt organizati pe straturi. Iesirile fiecarui
neuron dintr-un strat sunt conectate la intrarile tuturor neuronilor din stratul urmator.
Primul strat se cheama strat de intrare si este constituit din neuroni cu functia de
transfer identitate. Rolul lor este de a distribui fiecare intrare, catre toti neuronii din
stratul urmator. El are un numar de neuroni egal cu intrarile retelei. Ultimul strat se
cheama strat de iesire. Numarul de neuroni de iesire este egal, in cazul retelelor
folosite in clasificari (pattern recognition) cu numarul de clase distincte, posibile.
Toti neuronii dintr-o retea feed foward, in afara de cei din stratul de intrare,
sunt neuroni sigmoidali (functia de transfer f(x)=1/(1+exp(-x)). Deci raspunsul lor
este un numar real intre 0 si 1. Sunt folositi astfel de neuroni, si nu din cei cu raspuns
treapta, pentru ca algoritmul de antrenare (backpropagation) impune derivabilitatea
functiei de transfer.
Marea majoritate a retelelor feed forward folosite in aplicatii practice sunt cu
1 sau cu 2 strate ascunse. S-a demonstrat ca o retea neuronala cu 1 singur strat
ascuns, antrenata corespunzator, este capabila sa clasifice corect orice set de date de
intrare.
De asemenea, o retea cu 2 strate ascunse, antrenata corespunzator, este
capabila sa invete sa aproximeze o functie neliniara, cu aproximatie oricit de mica.
De aceea rareori, in practica, o retea feed forward e necesar sa aiba mai mult
de 1 sau 2 strate ascunse. Doar, daca, prin mai mult de 2 strate ascunse se obtine o
viteza de convergenta mai buna (mai putine iteratii in procesul de invatare).
Arhitectura retelei neuronale este partial impusa de problema si partial impusa
de rezultatele experimentale. Astfel, numarul de iesiri ( de clase) este impus de
problema. De exemplu, in aplicatia ce clasifica o curba data prin niste puncte de
intrare, in 5 clase (linie de panta 0, linie de panta pozitiva, linie de panta negativa,
curba convexa, curba concava ), in stratul de iesire trebuie sa fie 5 neuroni.
Numarul de neuroni de intrare este partial dat de problema, dar poate fi si
stabilit in functie de experienta,. Intrarile retelei pot fi: doar binare (digitale , deci
doar 2 valori posibile :0 sau 1), doar analogice, sau mixte.
Nu exista o formula care sa calculeze numarul de neuroni necesari in fiecare
strat ascuns. Acestia se determina experimental. Totusi, o recomandare posibila
(neobligatoriu de urmat !) este: daca sunt N neuroni de intrare, numarul de neuroni
din stratul ascuns, sa fie intre N si 2N.
De exemplu, pentru a invata functia XOR cu 2 intrari (vezi tabelul urmator:)

x1 x2 Y
0 0 0
0 1 1

L5 - 1 1
L4 - Reţele neuronale feed forward, cu două straturi ascunse

1 0 1
1 1 0
trebuie folosita o retea cu 2 neuroni pe intrare, 1 neuron de iesire , si un strat ascuns
cu 2 neuroni. Daca se foloseste doar 1 neuron in stratul ascuns: reteaua nu reuseste sa
invete functia. Daca se folosesc 3 neuroni in stratul ascuns, o invata mai rapid (in mai
putine iteratii).
Dezvoltarea unei aplicatii bazate pe o retea neuronala se face in 2 faze
(antrenare si testare).
In prima faza se face antrenarea retelei. Se pleaca de la un set de sabloane ce
trebuie invatate cu o anumita eroare. Sablonul este de fapt perechea intrarile retelei -
iesirile dorite ale retelei.. Alegerea sabloanelor are un rol cheie in implementarea cu
succes a unei aplicatii cu tehnologie neuronala. Sabloanele, de obicei pot fi:
- calculate matematic, ca in aplicatia dezvoltata in aceasta lucrare de laborator,
de aproximare a unei functii neliniare , f(x)=x2.
-memorate intr-un fisier pe disc, fisier editat manual sau generat printr-un
program soft.
Dimensiunea setului de sabloane se stabileste experimental. Sabloanele se pot
alege:
-uniform. Adica, un numar egal de sabloane pentru fiecare clasa de iesire.
-neuniform. Adica, un numar proportional cu probabilitatea de aparitie la
iesire a unei anumite clase.
Faza 2 este testarea retelei. Se prezinta retelei pe intrari le ei, intrari pe care ea
nu le-a invatat in faza de antrenare (forme, imagini noi). Se calculeaza iesirile retelei,
plecind de la intrari, din aproape in aproape. Daca este o problema de clasificare,
clasa este data de neuronul care are la iesire valoarea cea mai apropiata de 1.
Antrenarea retelelor neuronale feed forward se face cu algoritmul de
backpropagation. Ponderile se modifica pe baza diferentei dintre iesirile calculate de
retea si iesirile impuse de sabloanele de antrenare.
Ocazional, retelele neuronale se blocheaza in timpul invatarii. Fie, ia mult
timp invatarea unei probleme, fie nu reusesc s-o invete de loc. Totul depinde de
valorile alese initial pentru ponderi. Pentru a depasi aceasta problema pur si simplu se
reia antrenarea. Experimental, s-a observat ca o retea neuronala se comporta cel mai
bine la testare ( pentru date ce nu le-a vazut ), folosind cel mai mic numar de neuroni
in stratul ascuns, cu care setul de sabloane de antrenare este invatat corect. Deci, daca
vrem generalizari bune pe datele nevazute, antrenam reteaua folosind cel mai mic
numar de neuroni in stratul ascuns, ce poate invata cu succes setul de antrenare.
Daca reteaua nu poate invata setul de antrenare, trebuie operate una sau mai
multe din urmatoarele :
-se adauga mai multi neuroni in stratul ascuns
-se mareste sau se micsoreaza numarul de straturi ascunse
-se mareste numarul de epoci de antrenare
-se modifica parametrii in algoritmul de backpropagation
Daca reteaua se comporta nesatisfacator la testare (dupa ce a invatat setul de
sabloane), i se poate imbunatati performanta adaugand mai multe exemple de
antrenare (De exemplu, daca reteaua e antrenata pentru a invata recunoasterea
scrisului de mina, trebuie sa fie adaugate exemple de scris de la mai multe persoane).

3.DESFASURAREA LUCRARII
Pentru a ilustra capacitatea retelelor neuronale de a aproxima functii neliniare,
s-a ales ca exemplu de lucru aproximarea functiei f(x)=x2 :[0,1] ----> [0,1]

L5 - 2 2
L4 - Reţele neuronale feed forward, cu două straturi ascunse

In vederea rezolvarii problemei propuse, folosim o retea feed forward , total


conectata, cu 1 neuron in stratul de intrare, 2 strate ascunse , fiecare cu cate 5
neuroni, si 1 neuron in stratul de iesire.
Reteaua a fost antrenata pentru a invata 1000 de sabloane. Sabloanele sunt
calculate matematic, si anume perechi (x,y) : x=i/1000, unde i=0..999, si y=x2..
Reteaua a fost antrenata cu algoritmul de backpropagation.
Se va edita si apoi executa programul descris in continuare. Apoi in program
se vor opera modificarile precizate in tema asociata programului.

Listingul programului
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
#define NR_NEURONI_HIDDEN_IN 5
#define NR_NEURONI_HIDDEN_OUT 5
#define NR_TOTAL_EXEMPLE 1000
#define EROARE_IMPUSA 0.005
#define alfa 1.0
#define eta 1.0
#define NR_MAXIM_EPOCI 20000
#define ESC 27
void initPonderi(void);
int antrenare(void);
void incarcaExemple(void);
void calculIesiriNeuroni(double yHiddenIn[],double yHiddenOut[],
double *yOut,int ex);
void modificaPonderi(double yOut,double yHiddenOut[],
double yHiddenIn[],int ex);
void testare(void);

double exempleIn[NR_TOTAL_EXEMPLE];//are 1 neuron pe in


double exempleOut[NR_TOTAL_EXEMPLE];//are 1 neuron pe iesire
double w1[NR_NEURONI_HIDDEN_IN];//primul strat de ponderi
//w1[j] ponderea conexiunii de la neuronul din strat intrare
//la neuronul "j" din strat hiddenIn
double w2[NR_NEURONI_HIDDEN_OUT][NR_NEURONI_HIDDEN_IN];
double w3[NR_NEURONI_HIDDEN_OUT]; //al doilea strat de ponderi intre
// stratul hidden si stratul de iesire.

void main(void)
{
int converge;
int c;
clrscr();
//antrenare:
initPonderi();

L5 - 3 3
L4 - Reţele neuronale feed forward, cu două straturi ascunse

incarcaExemple();
converge=antrenare();
if(converge==0)printf("\n Nu a convers in nr. de epocii specificat !");
else{
printf("\n A convers. !");
testare();}//else
}//main

void initPonderi(void)
{
int i,j;
randomize();
for(j=0;j<NR_NEURONI_HIDDEN_IN;j++)
w1[j]=(double)rand()/RAND_MAX-0.5;

for(j=0;j<NR_NEURONI_HIDDEN_OUT;j++)
for(i=0;i<NR_NEURONI_HIDDEN_IN;i++)
w2[j][i]=(double)rand()/RAND_MAX-0.5;

for(i=0;i<NR_NEURONI_HIDDEN_OUT;i++)
w3[i]=(double)rand()/RAND_MAX-0.5;
}

void incarcaExemple(void)
{
double x;int i;
for(i=0;i<NR_TOTAL_EXEMPLE;i++){
x=i/1000.0;
exempleIn[i]=x;
exempleOut[i]=x*x;
}//for i
}

int antrenare(void)
{
int converge;
long int nrEpoci;
int stop;
double yHiddenIn[NR_NEURONI_HIDDEN_IN];
//iesiri neuroni din strat hiddenIn
double yHiddenOut[NR_NEURONI_HIDDEN_OUT];
//iesiri neuroni din strat hiddenOut
double yOut;//iesirea neuronuluii din stratul out (cea calculata)
double eroareIesireSablonCrt[NR_TOTAL_EXEMPLE];
double eroareTotala;
int c;
nrEpoci=0;
converge=0;
stop=0;
int i,ex;

L5 - 4 4
L4 - Reţele neuronale feed forward, cu două straturi ascunse

while(!stop){
for(ex=0;ex<NR_TOTAL_EXEMPLE;ex++){
calculIesiriNeuroni(yHiddenIn,yHiddenOut,&yOut,ex);//forward propagate
//eroarea de invatare a sablonului curent:
//Doa 1 neuron pe iesire:
eroareIesireSablonCrt[ex]=0.5*(yOut-exempleOut[ex])*(yOut-exempleOut[ex]);
modificaPonderi(yOut,yHiddenOut,yHiddenIn,ex);
}//for
//s-a terminat o epoca:
nrEpoci++;
//calcul eroare totala, pt. toate sabloanele:
eroareTotala=0;
for(ex=0;ex<NR_TOTAL_EXEMPLE;ex++)
eroareTotala+=eroareIesireSablonCrt[ex];
printf("\nEpoca nr: %ld, eroare totala = %lf",nrEpoci,eroareTotala);
if(eroareTotala <= EROARE_IMPUSA){converge=1;stop=1;}
else if(nrEpoci > NR_MAXIM_EPOCI)stop=1;
else if(kbhit()){
c=getch();
if(c==ESC)stop=1;
};
}//while
return converge;
}

void calculIesiriNeuroni(double yHiddenIn[],double yHiddenOut[],


double *yOut,int ex)
{
int i,j;
double xTotal;
for(j=0;j<NR_NEURONI_HIDDEN_IN;j++){
//Doar 1 neuron pe intrare:
xTotal=exempleIn[ex]*w1[j];
yHiddenIn[j]=1/(1+exp(-xTotal));
}//for j

for(j=0;j<NR_NEURONI_HIDDEN_OUT;j++){
xTotal=0;
for(i=0;i<NR_NEURONI_HIDDEN_IN;i++)
xTotal=xTotal+yHiddenIn[i]*w2[j][i];
//a calculat xTotal_j
yHiddenOut[j]=1/(1+exp(-xTotal));
}//for j
//Calcul yOut:
xTotal=0;
for(i=0;i<NR_NEURONI_HIDDEN_OUT;i++)
xTotal=xTotal+yHiddenOut[i]*w3[i];
//a calculat xTotal.
*yOut=1/(1+exp(-xTotal));
}

L5 - 5 5
L4 - Reţele neuronale feed forward, cu două straturi ascunse

void modificaPonderi(double yOut,double yHiddenOut[],


double yHiddenIn[],int ex)
{
double deltaOut;
double deltaHiddenOut[NR_NEURONI_HIDDEN_OUT];
double deltaHiddenIn[NR_NEURONI_HIDDEN_IN];
int i,j,k;
double sumaPonderataDeltaFii;
//double alfa=1.0;
//double eta=1.0;
//in nod iesire j: Wji=alfa*Wji-eta*delta_j*(Iesire neuron i)
// delta_j=(yCalculat_j - yDorit_j)*(derivata functiei de
// transfer sigmoide, in raport cu xTotal, in nodul j)
// derivata f. sigmoida y=1/(1=exp(-x)) este y'=(1-y)*y .
deltaOut=(yOut-exempleOut[ex])*(1-yOut)*yOut;
//corectie ponderi ce vin in nodul de iesire:
for(i=0;i<NR_NEURONI_HIDDEN_OUT;i++)
w3[i]=alfa*w3[i]-eta*deltaOut*yHiddenOut[i];
//in nodul j din hiddenOut:
// Wji=alfa*Wji-eta*delta_j*(Iesire neuron i, din strat ant.)
//delta_j=(Suma ponderata de delta_noduri_fii)*(derivata functiei de transfer
//sigmoide, in raport cu xTotal, in nodul j)
//derivata f. sigmoida y=1/(1=exp(-x)) este y'=(1-y)*y .
for(j=0;j<NR_NEURONI_HIDDEN_OUT;j++){
//nodul j are NR_NEURONI_OUT=1 noduri-fii, in strat urmator
sumaPonderataDeltaFii=w3[j]*deltaOut;
deltaHiddenOut[j]=sumaPonderataDeltaFii*
(1-yHiddenOut[j])*yHiddenOut[j];
}//for j
//corectie ponderi ce vin in nodurile hiddenOut, de la stratul de neuroni hiddenIn:
for(j=0;j<NR_NEURONI_HIDDEN_OUT;j++)
for(i=0;i<NR_NEURONI_HIDDEN_IN;i++)
w2[j][i]=alfa*w2[j][i]-eta*deltaHiddenOut[j]*yHiddenIn[i];

//in nodul j din hiddenIn:


for(j=0;j<NR_NEURONI_HIDDEN_IN;j++){
//nodul j are NR_NEURONI_HIDDEN_OUT noduri-fii, in strat urmator
sumaPonderataDeltaFii=0;
for(k=0;k<NR_NEURONI_HIDDEN_OUT;k++)
sumaPonderataDeltaFii+=w2[k][j]*deltaHiddenOut[k];
deltaHiddenIn[j]=sumaPonderataDeltaFii*(1-yHiddenIn[j])*yHiddenIn[j];
}//for j
//corectie ponderi ce vin in nodurile hiddenIn, de la stratul de
//neuroni IN (1 neuron):
for(j=0;j<NR_NEURONI_HIDDEN_IN;j++)
w1[j]=alfa*w1[j]-eta*deltaHiddenIn[j]*exempleIn[ex];
}//modificaPonderi

void testare(void)

L5 - 6 6
L4 - Reţele neuronale feed forward, cu două straturi ascunse

{
double yHiddenIn[NR_NEURONI_HIDDEN_IN];//iesiri neuroni din strat
hiddenIn
double yHiddenOut[NR_NEURONI_HIDDEN_OUT];
double yOut;//iesire neuron din stratul out.
//(cea calculata)
double yReal;
//double eroare;
printf("\n\nDati un nr. intre 0.0 si 1.0, x=");
scanf("%lf",&exempleIn[0]);//float este %f
calculIesiriNeuroni(yHiddenIn,yHiddenOut,&yOut,0);//forward propagate,
// pentru ex=0.
yReal=exempleIn[0]*exempleIn[0];
//eroare=( (yReal-yOut)/yReal )*100;//in procente
printf("\ny calculat de NN: %lf, y real: %lf",yOut,yReal);
getch();
}//testare

Tema
-Cum se modifica programul pentru ca reteaua sa invete aceeasi functie, dar
definita pe [0,2] cu valori in [0,4] ?
-Sa se modifice programul a.i. reteaua sa invete sa aproximeze functia
neliniara f(x)=x*x*x :[0,1] ---> [0,1]

4. CONCLUZII
Reteaua proiectata invata relativ repede setul de sabloane , iar erorile obtinute
la testare sunt destul de mici. Se puteau obtine erori la testare cu mult mai mici daca
se micsora eroarea globala de invatare a sabloanelor. In acest caz, timpul de antrenare
al retelei simulata pe un calculator secvential ar fi crescut .
Aceasta capacitate de aproximare a functiilor neliniare permite folosirea
retelelor neuronale in modelarea proceselor.

L5 - 7 7

S-ar putea să vă placă și