aggiornamento codice percettroni.h
This commit is contained in:
@@ -30,6 +30,9 @@ gcc -o rete_neurale rete_neurale.c -lm
|
||||
|
||||
# Automated training with pauses (prevents overheating)
|
||||
./addestratore.sh
|
||||
|
||||
# Memory leak detection (valgrind)
|
||||
valgrind --leak-check=full ./codice_ricordo
|
||||
```
|
||||
|
||||
### 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)
|
||||
2. Visual inspection of weight outputs via `stampa_pesi_rete()`
|
||||
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
|
||||
- `percettroni.h` - Core neural network (header-only library with implementations)
|
||||
|
||||
Binary file not shown.
+2
-20
@@ -3,32 +3,14 @@
|
||||
#define EPOCHE 100000
|
||||
|
||||
void main() {
|
||||
ReteNeurale rete = inizializza_rete_neurale(2, 2, 2);
|
||||
ReteNeurale rete = inizializza_rete_neurale(2, 5, 50, 10);
|
||||
//stampa_pesi_rete(rete);
|
||||
|
||||
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++) {
|
||||
printf("\nEPOCA %d\n", epoca);
|
||||
//printf("\nEPOCA %d\n", epoca);
|
||||
if (addestra(&rete, xor))
|
||||
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
@@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user