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
+4 -1
View File
@@ -30,6 +30,9 @@ gcc -o rete_neurale rete_neurale.c -lm
# Automated training with pauses (prevents overheating) # Automated training with pauses (prevents overheating)
./addestratore.sh ./addestratore.sh
# Memory leak detection (valgrind)
valgrind --leak-check=full ./codice_ricordo
``` ```
### Running a Single Test ### Running a Single Test
@@ -103,7 +106,7 @@ No formal test framework. Use these approaches:
1. `codice_ricordo.c` - XOR validation (4 inputs, quick convergence test) 1. `codice_ricordo.c` - XOR validation (4 inputs, quick convergence test)
2. Visual inspection of weight outputs via `stampa_pesi_rete()` 2. Visual inspection of weight outputs via `stampa_pesi_rete()`
3. Monitor epoch error rates in training output 3. Monitor epoch error rates in training output
4. Check for memory leaks with valgrind: `valgrind --leak-check=full ./codice_ricordo` 4. Check for memory leaks with valgrind
## Project Structure ## Project Structure
- `percettroni.h` - Core neural network (header-only library with implementations) - `percettroni.h` - Core neural network (header-only library with implementations)
BIN
View File
Binary file not shown.
+2 -20
View File
@@ -3,32 +3,14 @@
#define EPOCHE 100000 #define EPOCHE 100000
void main() { void main() {
ReteNeurale rete = inizializza_rete_neurale(2, 2, 2); ReteNeurale rete = inizializza_rete_neurale(2, 5, 50, 10);
//stampa_pesi_rete(rete); //stampa_pesi_rete(rete);
Dataset xor = *crea_dataset_xor(); Dataset xor = *crea_dataset_xor();
//for(int i = 0; i < xor->size; i++) {
// printf("%d\n", xor->istanze[i].classificazione);
//}
//double **sigmoidi;
/* for(int epoca = 0; epoca < EPOCHE; epoca++) {
for(int indice_istanza = 0; indice_istanza < xor->size; indice_istanza++) {
sigmoidi = elabora_sigmoidi(rete, xor->istanze[indice_istanza]);
}
} */
for(int epoca = 0; epoca < EPOCHE; epoca++) { for(int epoca = 0; epoca < EPOCHE; epoca++) {
printf("\nEPOCA %d\n", epoca); //printf("\nEPOCA %d\n", epoca);
if (addestra(&rete, xor)) if (addestra(&rete, xor))
break; break;
} }
//0:0 -> 0
/* sigmoidi = elabora_sigmoidi(rete, xor->istanze[0]);
int previsto = previsione(sigmoidi[rete.size -1][0]);
printf("La previsione per la prima istanza: %d\n", previsto); */
} }
+62 -44
View File
@@ -49,16 +49,16 @@ typedef struct
double randomico(); double randomico();
Percettrone inzializza_percettrone(int); Percettrone inzializza_percettrone(int);
ReteNeurale inizializza_rete_neurale(int, int, int); ReteNeurale inizializza_rete_neurale(int, int, int, int);
Layer inizializza_layer(int, int); Layer inizializza_layer(int, int);
double sigmoide(Percettrone p, double *); double sigmoide(Percettrone p, double *);
double derivata_sigmoide(double); double derivata_sigmoide(double);
double **elabora_sigmoidi(ReteNeurale, Istanza); double **elabora_sigmoidi(ReteNeurale *, Istanza);
double **elabora_gradienti(ReteNeurale, double, double **); double **elabora_gradienti(ReteNeurale *, double, double **);
void discesa_gradiente(ReteNeurale, double **, double **); void discesa_gradiente(ReteNeurale *, double **, double **);
double calcola_gradiente_disceso(ReteNeurale, int, int, double **); double calcola_gradiente_disceso(ReteNeurale *, int, int, double **);
void aggiorna_pesi(ReteNeurale *, double **, double **, Istanza); void aggiorna_pesi(ReteNeurale *, double **, double **, Istanza);
void correggi_pesi_percettrone_double(Percettrone *, int, double **, double); void correggi_pesi_percettrone_double(Percettrone *, int, double **, double);
@@ -69,7 +69,7 @@ int previsione(double);
void salvaReteNeurale(const char *, ReteNeurale *); void salvaReteNeurale(const char *, ReteNeurale *);
ReteNeurale *caricaReteNeurale(const char *); ReteNeurale *caricaReteNeurale(const char *);
void stampa_pesi_rete(ReteNeurale); void stampa_pesi_rete(ReteNeurale *);
/* /*
################# INIZIALIZZAZIONI ################################ ################# INIZIALIZZAZIONI ################################
@@ -79,6 +79,7 @@ double randomico()
{ {
// Genero numeri nell'intervallo [-1,1] // Genero numeri nell'intervallo [-1,1]
return ((double)(rand() % 101 * 0.01 * 2.0) - 1.0); return ((double)(rand() % 101 * 0.01 * 2.0) - 1.0);
//return (double)(rand() % 101 * 0.01);
} }
Percettrone inizializza_percettrone(int n_pesi) Percettrone inizializza_percettrone(int n_pesi)
@@ -112,22 +113,28 @@ Layer inizializza_layer(int n_percettroni, int n_pesi)
return layer; 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)); srand(time(NULL));
ReteNeurale r; ReteNeurale r;
r.layers = (Layer *)malloc(sizeof(Layer) * numero_layers); r.layers = (Layer *)malloc(sizeof(Layer) * numero_layers);
r.size = numero_layers; r.size = numero_layers;
// Funzione esponenziale inversa layer 5 // Funzione esponenziale inversa layer
for (int livello = 0; livello < numero_layers; livello++) for (int livello = 0; livello < numero_layers; livello++)
{ {
double esponente = (double)livello / (double)numero_layers; //double esponente = (double)livello / (double)numero_layers;
double frazione = (double)1 / (double)numero_percettroni_iniziali; //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) 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("esponente %f -> frazione: %f\n", esponente, frazione);
printf("Layer %d -> percettroni: %d\n", livello, numero_percettroni_livello); 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 // 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 // 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 // Qui mi trovo il gradiente del percettrone output (ultimo livello)
gradienti[rete_neurale.size - 1][0] = gradiente_errore * derivata_sigmoide(sigmoidi[rete_neurale.size - 1][0]); 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); discesa_gradiente(rete_neurale, sigmoidi, gradienti);
return gradienti; return gradienti;
@@ -210,11 +219,11 @@ int previsione(double valore)
} }
// Invocata da elabora_gradienti() // 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 derivata_attivazione = derivata_sigmoide(sigmoidi[indice_layer][indice_percettrone]);
double gradiente_disceso = calcola_gradiente_disceso(rete, indice_layer + 1, indice_percettrone, gradienti); 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() // 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; 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; return sommatoria;
} }
// Da eseguire a mano 1 // 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 **sigmoidi = (double **)malloc(sizeof(double *) * rete->size);
double *inputs = (double *)malloc(sizeof(double *) * N_INPUTS); double *inputs = (double *)malloc(sizeof(double) * N_INPUTS);
for (int i = 0; i < N_INPUTS; i++) for (int i = 0; i < N_INPUTS; i++)
{ {
inputs[i] = (double)istanza.dati[i]; inputs[i] = (double)istanza.dati[i];
} }
sigmoidi[0] = (double *)malloc(sizeof(double) * rete.layers[0].size); sigmoidi[0] = (double *)malloc(sizeof(double) * rete->layers[0].size);
for (int indice_percettrone = 0; indice_percettrone < rete.layers[0].size; indice_percettrone++) 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); 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++) 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 //Per ogni istanza del dataset
for (int indice_set = 0; indice_set < set.size; indice_set++) 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; byte output_corretto = set.istanze[indice_set].classificazione;
int previsto = previsione(sigmoidi[rete_neurale->size - 1][0]); 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) { if (previsto == output_corretto) {
corrette++; corrette++;
} }
@@ -351,13 +362,20 @@ byte addestra(ReteNeurale *rete_neurale, Dataset set)
double gradiente_errore = (output_corretto - sigmoidi[rete_neurale->size - 1][0]); double gradiente_errore = (output_corretto - sigmoidi[rete_neurale->size - 1][0]);
errore_totale += pow(gradiente_errore, 2); 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]); 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) if(corrette == set.size)
return 1; return 1;
@@ -460,17 +478,17 @@ ReteNeurale *caricaReteNeurale(const char *filename)
/* /*
################ STAMPE ############################ ################ 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); 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); 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]);
} }
} }
} }