aggiornamento codice percettroni.h

This commit is contained in:
2026-03-24 14:06:37 +01:00
parent 43732d156f
commit 524f33a690
4 changed files with 68 additions and 65 deletions
+62 -44
View File
@@ -49,16 +49,16 @@ typedef struct
double randomico();
Percettrone inzializza_percettrone(int);
ReteNeurale inizializza_rete_neurale(int, int, int);
ReteNeurale inizializza_rete_neurale(int, int, int, int);
Layer inizializza_layer(int, int);
double sigmoide(Percettrone p, double *);
double derivata_sigmoide(double);
double **elabora_sigmoidi(ReteNeurale, Istanza);
double **elabora_sigmoidi(ReteNeurale *, Istanza);
double **elabora_gradienti(ReteNeurale, double, double **);
void discesa_gradiente(ReteNeurale, double **, double **);
double calcola_gradiente_disceso(ReteNeurale, int, int, double **);
double **elabora_gradienti(ReteNeurale *, double, double **);
void discesa_gradiente(ReteNeurale *, double **, double **);
double calcola_gradiente_disceso(ReteNeurale *, int, int, double **);
void aggiorna_pesi(ReteNeurale *, double **, double **, Istanza);
void correggi_pesi_percettrone_double(Percettrone *, int, double **, double);
@@ -69,7 +69,7 @@ int previsione(double);
void salvaReteNeurale(const char *, ReteNeurale *);
ReteNeurale *caricaReteNeurale(const char *);
void stampa_pesi_rete(ReteNeurale);
void stampa_pesi_rete(ReteNeurale *);
/*
################# INIZIALIZZAZIONI ################################
@@ -79,6 +79,7 @@ double randomico()
{
// Genero numeri nell'intervallo [-1,1]
return ((double)(rand() % 101 * 0.01 * 2.0) - 1.0);
//return (double)(rand() % 101 * 0.01);
}
Percettrone inizializza_percettrone(int n_pesi)
@@ -112,22 +113,28 @@ Layer inizializza_layer(int n_percettroni, int n_pesi)
return layer;
}
ReteNeurale inizializza_rete_neurale(int numero_layers, int numero_percettroni_iniziali, int numero_input)
ReteNeurale inizializza_rete_neurale(int numero_input, int numero_layers, int numero_percettroni_iniziali, int numero_percettroni_finali)
{
srand(time(NULL));
ReteNeurale r;
r.layers = (Layer *)malloc(sizeof(Layer) * numero_layers);
r.size = numero_layers;
// Funzione esponenziale inversa layer 5
// Funzione esponenziale inversa layer
for (int livello = 0; livello < numero_layers; livello++)
{
double esponente = (double)livello / (double)numero_layers;
double frazione = (double)1 / (double)numero_percettroni_iniziali;
//double esponente = (double)livello / (double)numero_layers;
//double frazione = (double)1 / (double)numero_percettroni_iniziali;
//int numero_percettroni_livello = (int)((double)numero_percettroni_iniziali * pow(frazione, esponente));
int numero_percettroni_livello = 1;
int numero_percettroni_livello = (int)((double)numero_percettroni_iniziali * pow(frazione, esponente));
if (livello == numero_layers - 1)
numero_percettroni_livello = 1;
numero_percettroni_livello = numero_percettroni_finali;
else {
double frazione = (double) (numero_layers - livello) / (double) numero_layers;
numero_percettroni_livello = (int)((double)(numero_percettroni_iniziali * frazione));
}
// printf("esponente %f -> frazione: %f\n", esponente, frazione);
printf("Layer %d -> percettroni: %d\n", livello, numero_percettroni_livello);
@@ -146,19 +153,21 @@ ReteNeurale inizializza_rete_neurale(int numero_layers, int numero_percettroni_i
*/
// Da eseguire a mano 2
double **elabora_gradienti(ReteNeurale rete_neurale, double gradiente_errore, double **sigmoidi)
double **elabora_gradienti(ReteNeurale *rete_neurale, double gradiente_errore, double **sigmoidi)
{
double **gradienti = (double **)malloc(sizeof(double *) * rete_neurale.size);
double **gradienti = (double **)malloc(sizeof(double *) * rete_neurale->size);
// Alloco la dimensione per ogni layer
for (int indice_layer = 0; indice_layer < rete_neurale.size; indice_layer++)
for (int indice_layer = 0; indice_layer < rete_neurale->size; indice_layer++)
{
gradienti[indice_layer] = (double *)malloc(sizeof(double) * rete_neurale.layers[indice_layer].size);
gradienti[indice_layer] = (double *)malloc(sizeof(double) * rete_neurale->layers[indice_layer].size);
}
// Gradiente del percettrone output
gradienti[rete_neurale.size - 1][0] = gradiente_errore * derivata_sigmoide(sigmoidi[rete_neurale.size - 1][0]);
// Qui mi trovo il gradiente del percettrone output (ultimo livello)
for(int indice_percettrone = 0; indice_percettrone < rete_neurale->layers[rete_neurale->size - 1].size; indice_percettrone++)
gradienti[rete_neurale->size - 1][indice_percettrone] = gradiente_errore * derivata_sigmoide(sigmoidi[rete_neurale->size - 1][indice_percettrone]);
//Dal gradiente trovato per l'output, mi discendo tutti gli altri
discesa_gradiente(rete_neurale, sigmoidi, gradienti);
return gradienti;
@@ -210,11 +219,11 @@ int previsione(double valore)
}
// Invocata da elabora_gradienti()
void discesa_gradiente(ReteNeurale rete, double **sigmoidi, double **gradienti)
void discesa_gradiente(ReteNeurale *rete, double **sigmoidi, double **gradienti)
{
for (int indice_layer = rete.size - 2; indice_layer >= 0; indice_layer--)
for (int indice_layer = rete->size - 2; indice_layer >= 0; indice_layer--)
{
for (int indice_percettrone = 0; indice_percettrone < rete.layers[indice_layer].size; indice_percettrone++)
for (int indice_percettrone = 0; indice_percettrone < rete->layers[indice_layer].size; indice_percettrone++)
{
double derivata_attivazione = derivata_sigmoide(sigmoidi[indice_layer][indice_percettrone]);
double gradiente_disceso = calcola_gradiente_disceso(rete, indice_layer + 1, indice_percettrone, gradienti);
@@ -225,39 +234,39 @@ void discesa_gradiente(ReteNeurale rete, double **sigmoidi, double **gradienti)
}
// Invocata da discesa_gradienti()
double calcola_gradiente_disceso(ReteNeurale rete, int livello, int indice_peso, double **gradienti)
double calcola_gradiente_disceso(ReteNeurale *rete, int livello, int indice_peso, double **gradienti)
{
double sommatoria = 0.0;
for (int indice_percettrone = 0; indice_percettrone < rete.layers[livello].size; indice_percettrone++)
for (int indice_percettrone = 0; indice_percettrone < rete->layers[livello].size; indice_percettrone++)
{
sommatoria += (gradienti[livello][indice_percettrone] * rete.layers[livello].percettroni[indice_percettrone].pesi[indice_peso]);
sommatoria += (gradienti[livello][indice_percettrone] * rete->layers[livello].percettroni[indice_percettrone].pesi[indice_peso]);
}
return sommatoria;
}
// Da eseguire a mano 1
double **elabora_sigmoidi(ReteNeurale rete, Istanza istanza)
double **elabora_sigmoidi(ReteNeurale *rete, Istanza istanza)
{
double **sigmoidi = (double **)malloc(sizeof(double *) * rete.size);
double *inputs = (double *)malloc(sizeof(double *) * N_INPUTS);
double **sigmoidi = (double **)malloc(sizeof(double *) * rete->size);
double *inputs = (double *)malloc(sizeof(double) * N_INPUTS);
for (int i = 0; i < N_INPUTS; i++)
{
inputs[i] = (double)istanza.dati[i];
}
sigmoidi[0] = (double *)malloc(sizeof(double) * rete.layers[0].size);
for (int indice_percettrone = 0; indice_percettrone < rete.layers[0].size; indice_percettrone++)
sigmoidi[0] = (double *)malloc(sizeof(double) * rete->layers[0].size);
for (int indice_percettrone = 0; indice_percettrone < rete->layers[0].size; indice_percettrone++)
{
sigmoidi[0][indice_percettrone] = sigmoide(rete.layers[0].percettroni[indice_percettrone], inputs);
sigmoidi[0][indice_percettrone] = sigmoide(rete->layers[0].percettroni[indice_percettrone], inputs);
}
for (int indice_layer = 1; indice_layer < rete.size; indice_layer++)
for (int indice_layer = 1; indice_layer < rete->size; indice_layer++)
{
sigmoidi[indice_layer] = (double *)malloc(sizeof(double) * rete.layers[indice_layer].size);
for (int indice_percettrone = 0; indice_percettrone < rete.layers[indice_layer].size; indice_percettrone++)
sigmoidi[indice_layer] = (double *)malloc(sizeof(double) * rete->layers[indice_layer].size);
for (int indice_percettrone = 0; indice_percettrone < rete->layers[indice_layer].size; indice_percettrone++)
{
sigmoidi[indice_layer][indice_percettrone] = sigmoide(rete.layers[indice_layer].percettroni[indice_percettrone], sigmoidi[indice_layer - 1]);
sigmoidi[indice_layer][indice_percettrone] = sigmoide(rete->layers[indice_layer].percettroni[indice_percettrone], sigmoidi[indice_layer - 1]);
}
}
@@ -338,11 +347,13 @@ byte addestra(ReteNeurale *rete_neurale, Dataset set)
//Per ogni istanza del dataset
for (int indice_set = 0; indice_set < set.size; indice_set++)
{
double **sigmoidi = elabora_sigmoidi(*rete_neurale, set.istanze[indice_set]);
double **sigmoidi = elabora_sigmoidi(rete_neurale, set.istanze[indice_set]);
byte output_corretto = set.istanze[indice_set].classificazione;
int previsto = previsione(sigmoidi[rete_neurale->size - 1][0]);
printf("\tPrevisto: %d, corretto: %d\n", previsto, output_corretto);
//printf("\tPrevisto: %d, corretto: %d\n", previsto, output_corretto);
if (previsto == output_corretto) {
corrette++;
}
@@ -351,13 +362,20 @@ byte addestra(ReteNeurale *rete_neurale, Dataset set)
double gradiente_errore = (output_corretto - sigmoidi[rete_neurale->size - 1][0]);
errore_totale += pow(gradiente_errore, 2);
double **gradienti = elabora_gradienti(*rete_neurale, gradiente_errore, sigmoidi);
double **gradienti = elabora_gradienti(rete_neurale, gradiente_errore, sigmoidi);
aggiorna_pesi(rete_neurale, sigmoidi, gradienti, set.istanze[indice_set]);
for(int i = 0; i < rete_neurale->size; i++)
free(gradienti[i]);
free(gradienti);
}
for(int i = 0; i < rete_neurale->size; i++)
free(sigmoidi[i]);
free(sigmoidi);
}
printf("Errore: %f, risposte corrette: %d%\n", errore_totale, (corrette * 100) / set.size);
//printf("Errore: %f, risposte corrette: %d%\n", errore_totale, (corrette * 100) / set.size);
if(corrette == set.size)
return 1;
@@ -460,17 +478,17 @@ ReteNeurale *caricaReteNeurale(const char *filename)
/*
################ STAMPE ############################
*/
void stampa_pesi_rete(ReteNeurale rete)
void stampa_pesi_rete(ReteNeurale *rete)
{
for (int indice_layer = 0; indice_layer < rete.size; indice_layer++)
for (int indice_layer = 0; indice_layer < rete->size; indice_layer++)
{
printf("\nLivello %d", indice_layer);
for (int indice_percettrone = 0; indice_percettrone < rete.layers[indice_layer].size; indice_percettrone++)
for (int indice_percettrone = 0; indice_percettrone < rete->layers[indice_layer].size; indice_percettrone++)
{
printf("\n\tPercettrone %d", indice_percettrone);
for (int indice_peso = 0; indice_peso < rete.layers[indice_layer].percettroni[indice_percettrone].size; indice_peso++)
for (int indice_peso = 0; indice_peso < rete->layers[indice_layer].percettroni[indice_percettrone].size; indice_peso++)
{
printf("\n\t\tPeso %d: %f", indice_peso, rete.layers[indice_layer].percettroni[indice_percettrone].pesi[indice_peso]);
printf("\n\t\tPeso %d: %f", indice_peso, rete->layers[indice_layer].percettroni[indice_percettrone].pesi[indice_peso]);
}
}
}