Files
classificatore_immagini/percettroni_documentation.md
T

234 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.