8.5 KiB
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. Questo progetto educativo dimostra i principi fondamentali del deep learning in modo trasparente e accessibile.
📖 Documentazione Completa della Libreria percettroni.h
Panoramica
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 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_mnist.bin # Pesi salvati dopo l'addestramento
└── AGENTS.md # Guida per agenti di codifica
Compilazione e Esecuzione
Classificatore MNIST (default)
# Compila il classificatore
gcc -o classificatore_mnist classificatore.c -lm
# Esegue l'addestramento
./classificatore_mnist
Test XOR (validazione rapida)
Per verificare rapidamente che la rete converga correttamente:
-
Modifica
percettroni.h:- Commenta:
// #include "mnist/mnist_manager.h" - Decommenta:
#include "xor_manager.h"
- Commenta:
-
Compila ed esegui:
gcc -o classificatore_xor classificatore.c -lm
./classificatore_xor
Visualizzatore
gcc -o visualizzatore visualizzatore.c -lalleg -lm
Configurazione dell'Addestramento
Parametri Modificabili in classificatore.c
#define EPOCHE 500 // Numero massimo di epoche di addestramento
void main() {
// inizializza_rete_neurale(numero_input, numero_layers, percettroni_iniziali, percettroni_finali)
ReteNeurale rete = inizializza_rete_neurale(N_INPUTS, 2, 32, 10);
// ...
}
Parametri della rete neurale:
numero_input: Dimensione dell'input (784 per MNIST, 3072 per CIFAR-10)numero_layers: Numero totale di layer nella retepercettroni_iniziali: Numero di neuroni nel primo layer nascostopercettroni_finali: Numero di neuroni nell'ultimo layer (output)
Architettura automatica: I layer intermedi riducono progressivamente i neuroni secondo la formula:
neuroni_layer[i] = percettroni_iniziali * ((numero_layers - i) / numero_layers)
Costanti Modificabili in percettroni.h
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:
// Per MNIST (attivo di default)
#include "mnist/mnist_manager.h"
// Per XOR (testing rapido)
// #include "xor_manager.h"
// Per CIFAR-10
// #include "cifar-10/cifar10_manager.h"
Requisiti dei dataset:
- MNIST: File
t10k-images.idx3-ubyteet10k-labels.idx1-ubytenella cartellamnist/ - CIFAR-10: File binari appropriati nella cartella
cifar-10/ - XOR: Nessun file esterno richiesto (dataset hardcoded)
Processo di Addestramento
L'addestramento segue questo flusso completo:
- Inizializzazione: Creazione della rete con pesi casuali (inizializzazione He)
- Ciclo per epoca: Fino a
EPOCHEmassime o raggiungimento dellaTOLLERANZA - Forward propagation: Calcolo delle predizioni per ogni istanza
- Calcolo accuratezza: Percentuale di predizioni corrette
- Backpropagation: Calcolo dei gradienti dell'errore
- Aggiornamento pesi: Discesa del gradiente stocastica
- Arresto anticipato: Se accuratezza ≥
TOLLERANZA(99.5%) - 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
# Ispezione dettagliata dei pesi
// Decommenta in classificatore.c: stampa_pesi_rete(rete);
# Controllo memory leak
valgrind --leak-check=full ./classificatore_mnist
# Monitoraggio performance
time ./classificatore_mnist
Best Practice per l'Addestramento
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
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
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 di Sistema
- 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
floatper 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
valgrindper 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. Libero da utilizzare per apprendimento e ricerca.
💡 Suggerimento: Consulta la documentazione completa per comprendere le formule matematiche, gli algoritmi implementati e le proprietà teoriche di questa implementazione di rete neurale.