diff --git a/classificatore_singolo b/classificatore_singolo index 0719ddb..3d44c6e 100755 Binary files a/classificatore_singolo and b/classificatore_singolo differ diff --git a/classificatore_singolo.c b/classificatore_singolo.c index 15edcbf..e64b157 100644 --- a/classificatore_singolo.c +++ b/classificatore_singolo.c @@ -71,6 +71,7 @@ void main() { //gradienti è un array bidimensionale, la prima dimensione identifica il layer, la seconda il percettrone nel layer //gradienti[indice_layer][indice_percettrone] + //Questo vettore identifica i gradienti dei percettroni double **gradienti = (double**)malloc(sizeof(double*) * NUM_LAYERS); //Alloco la dimensione per ogni layer @@ -88,7 +89,27 @@ void main() { - gradiente dell'errore retropropagato = peso del ne */ - gradienti[NUM_LAYERS-1][0] = (output_corretto - sigmoidi[NUM_LAYERS-1][0]); + + double gradiente_errore = (output_corretto - sigmoidi[NUM_LAYERS-1][0]); + double derivata_sigmoide_out = sigmoidi[NUM_LAYERS-1][0] * (1 - sigmoidi[NUM_LAYERS-1][0]); + + gradienti[NUM_LAYERS-1][0] = gradiente_errore * derivata_sigmoide_out; + + //Ricorda di partire dal penultimo layer in quanto l'ultimo è già fatto + discesa_gradiente(rete_neurale, sigmoidi, gradienti); + + /* A questo punto ho tutti i gradienti dei percettroni, non mi resta che trovare i gradienti dei pesi e correggerli + */ + + //Applico la correzione dal penultimo layer andando indietro fino al secondo (il primo si fa diverso) + for(int indice_layer = NUM_LAYERS - 2; indice_layer > 0; indice_layer--) { + //Applico la correzione a tutti i percettroni del layer dal primo a seguire + for(int indice_percettrone = 0; indice_percettrone <= rete_neurale.layers[indice_layer].size; indice_percettrone++) { + correggi_pesi_percettrone(); + } + } + + //gradienti[NUM_LAYERS-1][0] = (output_corretto - sigmoidi[NUM_LAYERS-1][0]); errore_totale += gradienti[NUM_LAYERS-1][0]; correggi_layer_interni(&rete_neurale, gradienti, sigmoidi); diff --git a/percettroni.h b/percettroni.h index 4012f68..ff653d4 100644 --- a/percettroni.h +++ b/percettroni.h @@ -44,6 +44,9 @@ double *funzioni_attivazione_layer_double(Layer, double*); void correggi_layer_interni(ReteNeurale*, double**, double**); void correggi_layer_input(Layer*, double**, double**, byte*, int); +double calcola_gradiente_layer(ReteNeurale, int, int, double**); +void discesa_gradiente(ReteNeurale, double**, double**); + int previsione(double); void salvaReteNeurale(const char*, ReteNeurale*); @@ -211,7 +214,6 @@ void correggi_layer_interni(ReteNeurale *rete, double **gradienti, double **sigm } } } - //Questa funzione prende tutti i parametri della precedente + gli input passati dal dataset per correggere il layer di ingresso void correggi_layer_input(Layer *layer, double **gradienti, double **sigmoidi, byte *inputs, int n_layers) { //L'indice del layer d'ingresso che prende byte per input @@ -227,6 +229,39 @@ void correggi_layer_input(Layer *layer, double **gradienti, double **sigmoidi, b } } + +void discesa_gradiente(ReteNeurale rete, double **sigmoidi, double **gradienti) { + //For che scorre i layer dal penultimo al primo QUINI SIZE -2 + for(int indice_layer = rete.size -2; indice_layer >= 0; indice_layer--) { + //printf("Mi trovo nel layer %d, ho %d percettroni\n", indice_layer, rete.layers[indice_layer].size); + + //For che scorre i percettroni del layer partendo dal primo + //Per ogni percettrone mi devo prendere il gradiente disceso dal livello sopra e moltiplicarlo per la derivata di attivazione + for(int indice_percettrone = 0; indice_percettrone < rete.layers[indice_layer].size; indice_percettrone++) { + + double derivata_attivazione = sigmoidi[indice_layer][indice_percettrone] * (1 - sigmoidi[indice_layer][indice_percettrone]); + //Passo anche l'indice del percettrone perchè corrisponde all'indice del peso del livello sopra + double gradiente_disceso = calcola_gradiente_layer(rete, indice_layer + 1, indice_percettrone, gradienti); + + + gradienti[indice_layer][indice_percettrone] = gradiente_disceso * derivata_attivazione; + } + } +} + +double calcola_gradiente_disceso(ReteNeurale rete, int livello, int indice_peso, double **gradienti) { + //printf("Qui ci arrivo\n"); + double sommatoria = 0.0; + //printf("Layer %d: N_percettroni: %d\n", livello, rete.layers[livello].size); + //Calcolo la sommatoria dei gradienti dei percettroni per i pesi + for(int indice_percettrone = 0; indice_percettrone < rete.layers[livello].size; indice_percettrone++) { + sommatoria += (gradienti[livello][indice_peso] * rete.layers[livello].percettroni[indice_percettrone].pesi[indice_peso]); + } + + return sommatoria; +} + + //Una volta finito il ciclo delle epoche viene salvato lo stato della rete neurale void salvaReteNeurale(const char *filename, ReteNeurale *rete) { FILE *file = fopen(filename, "wb"); diff --git a/visualizzatore b/visualizzatore index cf86a31..9395e1e 100755 Binary files a/visualizzatore and b/visualizzatore differ