200 lines
5.1 KiB
Markdown
200 lines
5.1 KiB
Markdown
# 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.
|
||
|
||
## 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
|
||
|
||
## Struttura del Progetto
|
||
|
||
```
|
||
.
|
||
├── classificatore.c # Programma principale
|
||
├── percettroni.h # Libreria core della rete neurale (header-only)
|
||
├── 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
|
||
```
|
||
|
||
## Compilazione
|
||
|
||
### Classificatore MNIST (default)
|
||
```bash
|
||
gcc -o classificatore_mnist classificatore.c -lm
|
||
./classificatore_mnist
|
||
```
|
||
|
||
### Test XOR (validazione rapida)
|
||
Modifica `percettroni.h`:
|
||
- Commenta: `// #include "mnist/mnist_manager.h"`
|
||
- Decommenta: `#include "xor_manager.h"`
|
||
|
||
```bash
|
||
gcc -o classificatore_xor classificatore.c -lm
|
||
./classificatore_xor
|
||
```
|
||
|
||
### Visualizzatore
|
||
```bash
|
||
gcc -o visualizzatore visualizzatore.c -lalleg -lm
|
||
```
|
||
|
||
## Componenti Principali
|
||
|
||
### 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:**
|
||
|
||
```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
|
||
|
||
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%
|
||
}
|
||
}
|
||
```
|
||
|
||
### Manager Dataset
|
||
|
||
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
|
||
|
||
#### 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:
|
||
|
||
```c
|
||
// Per MNIST
|
||
#include "mnist/mnist_manager.h"
|
||
|
||
// Per XOR (testing)
|
||
// #include "xor_manager.h"
|
||
|
||
// Per CIFAR-10
|
||
// #include "cifar-10/cifar10_manager.h"
|
||
```
|
||
|
||
## Costanti Principali
|
||
|
||
- `LRE = 0.1`: learning rate
|
||
- `soglia_sigmoide = 0.5`: soglia per predizione binaria
|
||
- `EPOCHE`: numero epoche addestramento
|
||
|
||
## Debugging
|
||
|
||
```bash
|
||
# Ispezione pesi
|
||
stampa_pesi_rete(&rete);
|
||
|
||
# Controllo memory leak
|
||
valgrind --leak-check=full ./classificatore_mnist
|
||
|
||
# Monitoraggio training
|
||
// Modifica addestra() per stampare errore per epoca
|
||
```
|
||
|
||
## Note Tecniche
|
||
|
||
- **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)
|
||
|
||
## Esempio Output Training
|
||
|
||
```
|
||
Layer 0 -> percettroni: 256
|
||
Layer 1 -> percettroni: 230
|
||
...
|
||
Layer 9 -> percettroni: 10
|
||
Rete neurale da 123456 parametri
|
||
Risposte corrette: 85%
|
||
Risposte corrette: 92%
|
||
...
|
||
```
|
||
|
||
## Requisiti
|
||
|
||
- GCC o compilatore C compatibile
|
||
- Libreria math (`-lm`)
|
||
- Allegro (solo per visualizzatore)
|
||
|
||
## Licenza
|
||
|
||
Progetto didattico - Implementazione from-scratch per scopi educativi.
|