diff --git a/AGENTS.md b/AGENTS.md index 4186bbb..b92431f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,8 +29,8 @@ gcc -o classificatore_mnist classificatore.c -lm && ./classificatore_mnist # Memory leak detection valgrind --leak-check=full ./classificatore_mnist -# Run pre-compiled binary (50 epochs) -./classificatore_mnist_50_epoche +# Run pre-compiled binary +./classificatore ``` ### Running a Single Test @@ -88,10 +88,11 @@ gcc -o test_xor classificatore.c -lm && ./test_xor - Validate function inputs at entry points ## Key Constants (from percettroni.h) -- `LRE = 0.1` (learning rate) +- `LRE = 0.01` (learning rate) - `soglia_sigmoide = 0.5` (sigmoid threshold) -- `file_pesi = "rete_pesi.bin"` (model weights file) -- `SOFTMAX = 1` (use softmax for multi-class prediction) +- `file_pesi = "rete_mnist.bin"` (model weights file) +- `TOLLERANZA = 99.5` (accuracy tolerance for early stopping) +- `FUNZIONE_ATTIVAZIONE = 1` (0=sigmoid, 1=ReLU, 2=step function) ## Dataset Configuration In `percettroni.h`, include the desired dataset manager: @@ -106,6 +107,13 @@ No formal test framework. Use these approaches: 3. Monitor epoch error rates in training output 4. Check memory leaks with valgrind +## Linting and Type Checking +No formal linting or type checking tools are configured for this C project. Code quality is maintained through: +- Manual code review +- Compilation warnings (use `-Wall -Wextra` flags if needed) +- Valgrind for memory issues +- Consistent adherence to the style guidelines below + ## Project Structure - `percettroni.h` - Core neural network (header-only library) - `classificatore.c` - Main classifier program diff --git a/README.md b/README.md index 8ce6ca9..4f97d54 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,54 @@ # Classificatore di Immagini con Rete Neurale -Implementazione in C di una rete neurale from-scratch per la classificazione di immagini sui dataset MNIST e CIFAR-10. +Implementazione in C di una rete neurale **from-scratch** per la classificazione di immagini sui dataset MNIST e CIFAR-10. Questo progetto educativo dimostra i principi fondamentali del deep learning in modo trasparente e accessibile. + +📖 **[Documentazione Completa della Libreria percettroni.h](percettroni_documentation.md)** ## Panoramica -Questo progetto implementa una rete neurale fully-connected con: -- **Attivazione**: funzione sigmoide -- **Addestramento**: backpropagation con discesa del gradiente -- **Predizione**: softmax per classificazione multi-classe +Questa implementazione supporta reti neurali feedforward completamente connesse con: +- **Architettura dinamica**: Numero variabile di layer e neuroni per layer +- **Funzioni di attivazione**: Sigmoide, ReLU o gradino (configurabile) +- **Addestramento**: Backpropagation con discesa del gradiente stocastica +- **Classificazione**: Softmax per problemi multi-classe +- **Inizializzazione**: Strategia He per prevenire vanishing/exploding gradients ## Struttura del Progetto ``` . -├── classificatore.c # Programma principale +├── classificatore.c # Programma principale di addestramento ├── percettroni.h # Libreria core della rete neurale (header-only) +├── percettroni_documentation.md # Documentazione completa della libreria ├── xor_manager.h # Manager dataset XOR (4 campioni, test rapido) ├── mnist/ │ └── mnist_manager.h # Manager dataset MNIST (28x28 pixel) ├── cifar-10/ │ └── cifar10_manager.h # Manager dataset CIFAR-10 (32x32 RGB) ├── visualizzatore.c # Visualizzatore immagini (richiede Allegro) -└── rete_pesi.bin # Pesi pre-addestrati +├── rete_mnist.bin # Pesi salvati dopo l'addestramento +└── AGENTS.md # Guida per agenti di codifica ``` -## Compilazione +## Compilazione e Esecuzione ### Classificatore MNIST (default) ```bash +# Compila il classificatore gcc -o classificatore_mnist classificatore.c -lm + +# Esegue l'addestramento ./classificatore_mnist ``` ### Test XOR (validazione rapida) -Modifica `percettroni.h`: -- Commenta: `// #include "mnist/mnist_manager.h"` -- Decommenta: `#include "xor_manager.h"` +Per verificare rapidamente che la rete converga correttamente: +1. Modifica `percettroni.h`: + - Commenta: `// #include "mnist/mnist_manager.h"` + - Decommenta: `#include "xor_manager.h"` + +2. Compila ed esegui: ```bash gcc -o classificatore_xor classificatore.c -lm ./classificatore_xor @@ -47,153 +59,192 @@ gcc -o classificatore_xor classificatore.c -lm gcc -o visualizzatore visualizzatore.c -lalleg -lm ``` -## Componenti Principali +## Configurazione dell'Addestramento -### percettroni.h - -Libreria header-only che implementa la rete neurale completa. - -**Strutture dati:** -- `Percettrone`: singolo neurone con pesi, bias e dimensione -- `Layer`: strato di percettroni -- `ReteNeurale`: rete completa con array di layer - -**Funzioni principali:** +### Parametri Modificabili in `classificatore.c` ```c -// Inizializzazione -ReteNeurale inizializza_rete_neurale(int numero_input, int numero_layers, - int numero_percettroni_iniziali, - int numero_percettroni_finali); - -// Forward propagation -double **elabora_sigmoidi(ReteNeurale *rete, Istanza istanza); - -// Backpropagation -double **elabora_gradienti(ReteNeurale *rete, byte output_corretto, double **sigmoidi); -void aggiorna_pesi(ReteNeurale *rete, double **sigmoidi, double **gradienti, Istanza istanza); - -// Predizione -int previsione_softmax(double *output, int size); - -// Persistenza -void salvaReteNeurale(const char *filename, ReteNeurale *rete); -ReteNeurale *caricaReteNeurale(const char *filename); -``` - -**Architettura dinamica:** -I layer intermedi riducono progressivamente i percettroni secondo la formula: -``` -percettroni = percettroni_iniziali * (layer_rimanenti / layer_totali) -``` - -### classificatore.c - -Programma principale che configura e addestra la rete. - -```c -#define EPOCHE 50 +#define EPOCHE 500 // Numero massimo di epoche di addestramento void main() { - // Rete: 784 input (MNIST), 10 layer, 256 percettroni iniziali, 10 output - ReteNeurale rete = inizializza_rete_neurale(N_INPUTS, 10, 256, 10); - Dataset mnist = *get_dataset(); - - for(int epoca = 0; epoca < EPOCHE; epoca++) { - if (addestra(&rete, mnist)) - break; // Stop se accuratezza 100% - } + // inizializza_rete_neurale(numero_input, numero_layers, percettroni_iniziali, percettroni_finali) + ReteNeurale rete = inizializza_rete_neurale(N_INPUTS, 2, 32, 10); + // ... } ``` -### Manager Dataset +**Parametri della rete neurale:** +- `numero_input`: Dimensione dell'input (784 per MNIST, 3072 per CIFAR-10) +- `numero_layers`: Numero totale di layer nella rete +- `percettroni_iniziali`: Numero di neuroni nel primo layer nascosto +- `percettroni_finali`: Numero di neuroni nell'ultimo layer (output) -Ogni manager definisce: -- `N_INPUTS`: dimensione input (es. 784 per MNIST 28x28) -- `Istanza`: struct con `classificazione` e `dati[]` -- `Dataset`: struct con array di istanze e dimensione -- `get_dataset()`: funzione che carica i dati +**Architettura automatica:** I layer intermedi riducono progressivamente i neuroni secondo la formula: +``` +neuroni_layer[i] = percettroni_iniziali * ((numero_layers - i) / numero_layers) +``` -#### xor_manager.h -Dataset semplice per test (4 campioni): -- Input: 2 valori binari -- Output: 1 valore (XOR) -- Perfetto per verificare convergenza - -#### mnist/mnist_manager.h -Dataset MNIST: -- Input: 784 pixel (28×28) -- Output: 10 classi (cifre 0-9) -- Formato IDX: header binario + pixel raw -- Supporta train (60k) e test (10k) set - -#### cifar-10/cifar10_manager.h -Dataset CIFAR-10: -- Input: 3072 valori (32×32 RGB) -- Output: 10 classi (oggetti) -- Formato binario: label + pixel RGB - -## Configurazione Dataset - -In `percettroni.h`, includi il manager desiderato: +### Costanti Modificabili in `percettroni.h` ```c -// Per MNIST +float LRE = 0.01; // Learning Rate (tasso di apprendimento) +float soglia_sigmoide = 0.5; // Soglia per classificazione binaria +#define TOLLERANZA 99.5 // Accuratezza % per arresto anticipato +#define FUNZIONE_ATTIVAZIONE 1 // 0=sigmoide, 1=ReLU, 2=gradino +char *file_pesi = "rete_mnist.bin"; // File per salvataggio pesi +``` + +### Selezione del Dataset + +In `percettroni.h`, includi solo il manager del dataset desiderato: + +```c +// Per MNIST (attivo di default) #include "mnist/mnist_manager.h" -// Per XOR (testing) +// Per XOR (testing rapido) // #include "xor_manager.h" // Per CIFAR-10 // #include "cifar-10/cifar10_manager.h" ``` -## Costanti Principali +**Requisiti dei dataset:** +- **MNIST**: File `t10k-images.idx3-ubyte` e `t10k-labels.idx1-ubyte` nella cartella `mnist/` +- **CIFAR-10**: File binari appropriati nella cartella `cifar-10/` +- **XOR**: Nessun file esterno richiesto (dataset hardcoded) -- `LRE = 0.1`: learning rate -- `soglia_sigmoide = 0.5`: soglia per predizione binaria -- `EPOCHE`: numero epoche addestramento +## Processo di Addestramento -## Debugging +L'addestramento segue questo flusso completo: + +1. **Inizializzazione**: Creazione della rete con pesi casuali (inizializzazione He) +2. **Ciclo per epoca**: Fino a `EPOCHE` massime o raggiungimento della `TOLLERANZA` +3. **Forward propagation**: Calcolo delle predizioni per ogni istanza +4. **Calcolo accuratezza**: Percentuale di predizioni corrette +5. **Backpropagation**: Calcolo dei gradienti dell'errore +6. **Aggiornamento pesi**: Discesa del gradiente stocastica +7. **Arresto anticipato**: Se accuratezza ≥ `TOLLERANZA` (99.5%) +8. **Salvataggio**: Scrittura dei pesi finali su `rete_mnist.bin` + +### Output di Esempio +``` +Layer 0 -> percettroni: 32 +Layer 1 -> percettroni: 10 +Rete neurale da 25354 parametri + +EPOCA 0 +Risposte corrette: 12.34% + +EPOCA 1 +Risposte corrette: 45.67% +... +EPOCA 25 +Risposte corrette: 99.60% +``` + +## Caratteristiche Avanzate + +### Funzioni di Attivazione Supportate + +**ReLU (default - più efficiente):** +- Formula: `f(x) = max(0, x)` +- Vantaggi: Nessun vanishing gradient, computazionalmente efficiente + +**Sigmoide:** +- Formula: `f(x) = 1 / (1 + e^(-x))` +- Uso: Tradizionale per output binari, ma soffre di vanishing gradient + +**Gradino:** +- Formula: `f(x) = 1 se x > 0, altrimenti 0` +- Limitazione: Non differenziabile, non utilizzabile con backpropagation + +### Gestione della Memoria + +- **Allocazione dinamica**: Tutti gli array sono allocati dinamicamente +- **Pulizia automatica**: La memoria viene liberata correttamente dopo ogni epoca +- **Persistenza**: Supporto per salvataggio/caricamento di reti addestrate + +### Debugging e Analisi ```bash -# Ispezione pesi -stampa_pesi_rete(&rete); +# Ispezione dettagliata dei pesi +// Decommenta in classificatore.c: stampa_pesi_rete(rete); # Controllo memory leak valgrind --leak-check=full ./classificatore_mnist -# Monitoraggio training -// Modifica addestra() per stampare errore per epoca +# Monitoraggio performance +time ./classificatore_mnist ``` -## Note Tecniche +## Best Practice per l'Addestramento -- **Normalizzazione**: input byte (0-255) convertiti in double (0.0-1.0) -- **Inizializzazione**: pesi casuali in [-1, 1] -- **Attivazione**: sigmoide con formula `1/(1+e^(-x))` -- **Softmax**: usato solo sull'output per probabilità multi-classe -- **Prestazioni**: training CPU-intensive (minuti per epoca su MNIST) +### Scelta dell'Architettura +- **Reti profonde** (>5 layer): Richiedono più dati e tempo di addestramento +- **Reti larghe**: Più neuroni per layer aumentano la capacità ma anche l'overfitting +- **Architettura a imbuto**: Riduzione progressiva dei neuroni è generalmente efficace -## Esempio Output Training +### Ottimizzazione degli Iperparametri +- **Learning Rate**: + - Troppo alto (>0.1): Instabilità, divergenza + - Troppo basso (<0.001): Convergenza lenta + - Valore consigliato: 0.01 (default) +- **Numero di epoche**: Dipende dalla complessità del dataset + - XOR: 100-500 epoche sufficienti + - MNIST: 500+ epoche per buone prestazioni -``` -Layer 0 -> percettroni: 256 -Layer 1 -> percettroni: 230 -... -Layer 9 -> percettroni: 10 -Rete neurale da 123456 parametri -Risposte corrette: 85% -Risposte corrette: 92% -... -``` +### Prevenzione dell'Overfitting +- **Arresto anticipato**: Implementato con soglia del 99.5% +- **Dataset adeguato**: Utilizzare set di training/test separati +- **Architettura semplice**: Evitare reti troppo complesse per il dataset -## Requisiti +## Requisiti di Sistema -- GCC o compilatore C compatibile -- Libreria math (`-lm`) -- Allegro (solo per visualizzatore) +- **Compilatore**: GCC o qualsiasi compilatore C standard +- **Librerie**: math (`-lm`) obbligatoria, Allegro opzionale (solo visualizzatore) +- **Memoria**: Dipende dall'architettura della rete (MNIST richiede ~100MB) +- **Dataset**: MNIST (~11MB), CIFAR-10 (~160MB) + +## Note Tecniche Importanti + +- **Normalizzazione input**: I valori pixel (0-255) vengono convertiti automaticamente in (0.0-1.0) +- **Precisione**: Utilizzo di `float` per tutti i calcoli (bilancio tra precisione e memoria) +- **Performance**: Implementazione CPU-only, ottimizzata per chiarezza piuttosto che velocità +- **Determinismo**: Il seed random è basato su `time(NULL)`, quindi ogni esecuzione è diversa + +## Risoluzione Problemi Comuni + +**"Errore nell'apertura del file"**: +- Verifica che i file del dataset siano nella posizione corretta +- Controlla i permessi di lettura + +**Addestramento troppo lento**: +- Riduci il numero di layer/neuroni +- Usa il dataset XOR per test rapidi +- Verifica che il learning rate non sia troppo basso + +**Accuratezza bassa**: +- Aumenta il numero di epoche +- Prova architetture diverse +- Verifica la qualità del dataset + +**Memory leak**: +- Assicurati di usare `valgrind` per identificare problemi +- La libreria gestisce correttamente la memoria in condizioni normali + +## Estensioni Future + +- **Batch training**: Implementazione della discesa del gradiente mini-batch +- **Regularizzazione**: Dropout, L1/L2 regularization +- **Ottimizzatori avanzati**: Adam, RMSprop +- **Convoluzioni**: Supporto per reti neurali convoluzionali (CNN) ## Licenza -Progetto didattico - Implementazione from-scratch per scopi educativi. +Progetto didattico - Implementazione from-scratch per scopi educativi. +Libero da utilizzare per apprendimento e ricerca. + +--- + +💡 **Suggerimento**: Consulta la [documentazione completa](percettroni_documentation.md) per comprendere le formule matematiche, gli algoritmi implementati e le proprietà teoriche di questa implementazione di rete neurale. \ No newline at end of file diff --git a/cifar-10/cifar10_manager.h b/cifar-10/cifar10_manager.h index 7e58c47..015e775 100644 --- a/cifar-10/cifar10_manager.h +++ b/cifar-10/cifar10_manager.h @@ -1,6 +1,13 @@ #include #include +// char *file_immagini = "cifar-10/data_batch_1.bin"; +// char *file_immagini = "cifar-10/data_batch_2.bin"; +// char *file_immagini = "cifar-10/data_batch_3.bin"; +// char *file_immagini = "cifar-10/data_batch_4.bin"; +// char *file_immagini = "cifar-10/data_batch_5.bin"; +// char *file_immagini = "cifar-10/test_batch.bin"; + #define N_INPUTS 3072 // 1024 pixel * 3 (R, G, B) // Siccome il char è un byte che rappresenta il valore tra 0 e 255. Per evitare confusioni definisco il tipo "byte" come in Java @@ -49,8 +56,8 @@ Dataset *get_dataset(char *path) } // Dataset set; - (*set).size = numero_righe; - (*set).istanze = istanze; + set->size = numero_righe; + set->istanze = istanze; fclose(file); diff --git a/classificatore b/classificatore index 6d6f816..bdd81b3 100755 Binary files a/classificatore and b/classificatore differ diff --git a/percettroni.h b/percettroni.h index adb29e7..81889a1 100644 --- a/percettroni.h +++ b/percettroni.h @@ -7,14 +7,7 @@ char *file_pesi = "rete_mnist.bin"; #include "mnist/mnist_manager.h" - // #include "cifar-10/cifar10_manager.h"; -// char *file_immagini = "cifar-10/data_batch_1.bin"; -// char *file_immagini = "cifar-10/data_batch_2.bin"; -// char *file_immagini = "cifar-10/data_batch_3.bin"; -// char *file_immagini = "cifar-10/data_batch_4.bin"; -// char *file_immagini = "cifar-10/data_batch_5.bin"; -// char *file_immagini = "cifar-10/test_batch.bin"; typedef unsigned char byte; diff --git a/percettroni_documentation.md b/percettroni_documentation.md new file mode 100644 index 0000000..3f19b5b --- /dev/null +++ b/percettroni_documentation.md @@ -0,0 +1,234 @@ +# Documentazione della Libreria `percettroni.h` + +Questa libreria implementa una rete neurale feedforward completamente connessa (fully-connected) in linguaggio C puro, progettata per la classificazione di immagini sui dataset MNIST e CIFAR-10. L'implementazione segue i principi fondamentali del deep learning con backpropagation e discesa del gradiente stocastica. + +## Struttura dei Dati + +### Percettrone +Il **percettrone** è l'unità fondamentale di calcolo nella rete neurale, ispirato al modello biologico del neurone. + +```c +typedef struct { + float *pesi; // Vettore dei pesi sinaptici + float bias; // Bias (soglia di attivazione) + int size; // Numero di input (dimensione del vettore pesi) +} Percettrone; +``` + +**Proprietà matematiche:** +- Ogni percettrone calcola una combinazione lineare degli input: `z = Σ(w_i * x_i) + b` +- La funzione di attivazione trasforma questo valore in un output non lineare +- I pesi rappresentano la "forza" delle connessioni sinaptiche +- Il bias permette di spostare la soglia di attivazione + +### Layer +Un **layer** (strato) è un insieme di percettroni che operano in parallelo sugli stessi input. + +```c +typedef struct { + Percettrone *percettroni; // Array di percettroni + int size; // Numero di percettroni nello strato +} Layer; +``` + +### ReteNeurale +La **rete neurale** è composta da una sequenza di layer interconnessi. + +```c +typedef struct { + Layer *layers; // Array di layer + int size; // Numero totale di layer +} ReteNeurale; +``` + +## Costanti Fondamentali + +- **`LRE = 0.01`**: Learning Rate (tasso di apprendimento) - controlla la dimensione dei passi nella discesa del gradiente +- **`soglia_sigmoide = 0.5`**: Soglia per la classificazione binaria con funzione sigmoide +- **`TOLLERANZA = 99.5`**: Percentuale di accuratezza richiesta per l'arresto anticipato dell'addestramento +- **`FUNZIONE_ATTIVAZIONE = 1`**: Tipo di funzione di attivazione (0=sigmoide, 1=ReLU, 2=gradino) + +## Funzioni di Inizializzazione + +### `inizializza_percettrone(int n_pesi)` +**Descrizione:** Inizializza un singolo percettrone con pesi casuali secondo la strategia di **inizializzazione He**. + +**Implementazione matematica:** +- Utilizza il Teorema Centrale del Limite per generare pesi distribuiti normalmente +- Deviazione standard: `σ = √(2/n)` dove `n` è il numero di input +- Formula: `peso = (Σ₁₂(rand()) - 6) × √(2/n)` +- Il bias viene inizializzato a 0 + +**Proprietà:** Questa inizializzazione previene il problema del vanishing/exploding gradient nelle reti profonde con ReLU. + +### `inizializza_layer(int n_percettroni, int n_pesi)` +**Descrizione:** Crea un layer completo con un numero specificato di percettroni, ognuno con lo stesso numero di pesi. + +**Architettura dinamica:** La libreria supporta architetture con riduzione progressiva del numero di neuroni: +- Layer intermedi: `neuroni = neuroni_iniziali × (layer_rimanenti / layer_totali)` +- Questo crea una struttura a imbuto che estrae caratteristiche sempre più astratte + +### `inizializza_rete_neurale(int numero_input, int numero_layers, int numero_percettroni_iniziali, int numero_percettroni_finali)` +**Descrizione:** Costruisce l'intera rete neurale con architettura personalizzabile. + +**Caratteristiche:** +- Supporta reti profonde con qualsiasi numero di layer +- Configurazione flessibile del numero di neuroni per layer +- Calcolo automatico del numero totale di parametri (pesi + bias) + +## Funzioni di Attivazione e Previsione + +### `attivazione(Percettrone p, float *valori)` +**Descrizione:** Calcola l'output di un percettrone applicando la funzione di attivazione scelta. + +**Formule matematiche implementate:** + +1. **Sigmoide (FUNZIONE_ATTIVAZIONE = 0):** + ``` + σ(z) = 1 / (1 + e^(-z)) + ``` + - Output nell'intervallo (0, 1) + - Derivata: `σ'(z) = σ(z) × (1 - σ(z))` + +2. **ReLU (FUNZIONE_ATTIVAZIONE = 1):** + ``` + ReLU(z) = max(0, z) + ``` + - Output nell'intervallo [0, ∞) + - Derivata: `ReLU'(z) = 1 se z > 0, altrimenti 0` + +3. **Gradino (FUNZIONE_ATTIVAZIONE = 2):** + ``` + step(z) = 1 se z > 0, altrimenti 0 + ``` + - Output binario {0, 1} + - Derivata: sempre 0 (non utilizzabile per backpropagation) + +### `derivata_attivazione(float valore)` +**Descrizione:** Calcola la derivata della funzione di attivazione rispetto all'input. + +**Importanza nel backpropagation:** La derivata è essenziale per calcolare i gradienti durante l'addestramento, permettendo alla rete di apprendere attraverso la regola della catena. + +### `softmax(float *input, int size)` +**Descrizione:** Applica la funzione softmax al layer di output per la classificazione multi-classe. + +**Formula matematica:** +``` +softmax(z_i) = e^(z_i) / Σⱼ(e^(z_j)) +``` + +**Proprietà:** +- Trasforma gli output in probabilità che sommano a 1 +- È differenziabile, permettendo l'uso con backpropagation +- Implementazione numerica stabile con sottrazione del massimo per evitare overflow + +### `previsione_softmax(float *livello_percettroni, int size)` +**Descrizione:** Esegue la classificazione finale applicando softmax e restituendo l'indice della classe con probabilità massima. + +## Forward Propagation + +### `elabora_attivazioni(ReteNeurale *rete, Istanza istanza)` +**Descrizione:** Esegue il forward propagation attraverso l'intera rete, calcolando le attivazioni di tutti i neuroni. + +**Processo:** +1. Normalizza gli input pixel (0-255 → 0.0-1.0) +2. Propaga sequenzialmente attraverso ogni layer +3. Restituisce una matrice 2D con tutte le attivazioni intermedie + +**Importanza:** Le attivazioni intermedie sono necessarie per il calcolo dei gradienti durante il backpropagation. + +## Backpropagation e Discesa del Gradiente + +### `elabora_gradienti(ReteNeurale *rete_neurale, byte output, float **attivazioni)` +**Descrizione:** Calcola i gradienti dell'errore rispetto ai pesi utilizzando l'algoritmo di backpropagation. + +**Algoritmo matematico:** +- **Layer di output:** `δ_output = y_true - y_pred` (per perdita cross-entropy con softmax) +- **Layer nascosti:** `δ_hidden = (W^T × δ_next) ⊙ f'(z)` + - Dove `⊙` è il prodotto elemento-per-elemento (Hadamard product) + - `f'(z)` è la derivata della funzione di attivazione + +### `discesa_gradiente(ReteNeurale *rete, float **attivazioni, float **gradienti)` +**Descrizione:** Propaga i gradienti all'indietro attraverso i layer nascosti. + +**Regola della catena:** Applica ricorsivamente la regola della catena per calcolare i gradienti nei layer precedenti. + +### `calcola_gradiente_disceso(ReteNeurale *rete, int livello, int indice_peso, float **gradienti)` +**Descrizione:** Calcola il contributo aggregato di un peso specifico al gradiente del layer successivo. + +**Formula:** `gradiente_disceso = Σ(δ_j × w_ji)` dove `j` indica i neuroni del layer successivo. + +## Aggiornamento dei Pesi + +### `aggiorna_pesi(ReteNeurale *rete_neurale, float **attivazioni, float **gradienti, Istanza istanza)` +**Descrizione:** Aggiorna tutti i pesi e bias della rete utilizzando la discesa del gradiente stocastica. + +**Regola di aggiornamento:** +``` +w_new = w_old + η × δ × input +b_new = b_old + η × δ +``` +Dove `η` è il learning rate (`LRE`) e `δ` è il gradiente dell'errore. + +### `correggi_pesi_percettrone_float()` e `correggi_pesi_percettrone_byte()` +**Descrizione:** Funzioni specializzate per l'aggiornamento dei pesi nel primo layer (che riceve input grezzi come byte) e nei layer successivi (che ricevono attivazioni normalizzate come float). + +## Addestramento + +### `addestra(ReteNeurale *rete_neurale, Dataset set)` +**Descrizione:** Esegue un'epoca completa di addestramento sul dataset fornito. + +**Processo completo:** +1. Per ogni istanza nel dataset: + - Forward propagation per ottenere le predizioni + - Calcolo dell'accuratezza corrente + - Backpropagation per calcolare i gradienti + - Aggiornamento dei pesi +2. Calcolo della percentuale di risposte corrette +3. Arresto anticipato se l'accuratezza supera la `TOLLERANZA` + +**Caratteristiche:** +- Implementa la discesa del gradiente stocastica (SGD) +- Supporta l'arresto anticipato per prevenire overfitting +- Fornisce feedback sull'accuratezza durante l'addestramento + +## Persistenza + +### `salvaReteNeurale(const char *filename, ReteNeurale *rete)` +**Descrizione:** Salva l'intera rete su file binario in formato proprietario. + +**Formato:** Struttura annidata che preserva esattamente la topologia e i valori dei pesi. + +### `caricaReteNeurale(const char *filename)` +**Descrizione:** Carica una rete precedentemente salvata da file. + +**Utilizzo:** Permette di riprendere l'addestramento o di utilizzare modelli pre-addestrati. + +## Debugging e Analisi + +### `stampa_pesi_rete(ReteNeurale *rete)` +**Descrizione:** Stampa tutti i pesi e bias della rete in formato leggibile. + +**Utilizzo:** Essenziale per il debugging e l'analisi del comportamento della rete durante l'addestramento. + +## Proprietà Matematiche della Rete + +### Architettura Feedforward +- Informazione che fluisce solo in avanti (input → output) +- Nessuna connessione ricorrente o laterale +- Computazione deterministica e parallela all'interno di ogni layer + +### Universal Approximation Theorem +Questa implementazione, essendo una rete feedforward con almeno uno strato nascosto e funzioni di attivazione non lineari, può approssimare qualsiasi funzione continua con precisione arbitraria, dato un numero sufficiente di neuroni. + +### Ottimizzazione +- **Funzione di perdita:** Implicitamente cross-entropy (grazie all'uso di softmax e backpropagation) +- **Algoritmo di ottimizzazione:** Discesa del gradiente stocastica +- **Regularizzazione:** Nessuna esplicita, ma l'inizializzazione He e l'arresto anticipato aiutano a prevenire overfitting + +### Complessità Computazionale +- **Forward propagation:** O(N×M) dove N è il numero totale di neuroni e M il numero di connessioni +- **Backpropagation:** O(N×M) - stessa complessità del forward pass +- **Memoria:** O(N×M) per memorizzare pesi, gradienti e attivazioni intermedie + +Questa libreria rappresenta un'implementazione educativa completa di una rete neurale moderna, dimostrando i principi fondamentali del deep learning in modo trasparente e accessibile. \ No newline at end of file diff --git a/rete_mnist.bin b/rete_mnist.bin index 1cc1bde..1692f3e 100644 Binary files a/rete_mnist.bin and b/rete_mnist.bin differ