In questo articolo cercheremo di esplorare, con un linguaggio semplice e accessibile, come funziona una rete neurale. L’obiettivo di questo scritto è puramente divulgativo: si rivolge a chi non è esperto di algebra lineare, o magari l’ha studiata tempo fa e non la ricorda più, a chi non ha familiarità con la programmazione in Python, e, naturalmente, a chi non lavora già come data scientist o specialista in deep learning.
L’idea di affrontare questo tema è nata durante una chiacchierata con il mio amico Riccardo. Entrambi abbiamo una formazione legata all’informatica classica, quella che si basa su modelli deterministici, certi e prevedibili. Discutendo, ci siamo resi conto di quanto sia difficile spiegare un approccio euristico come quello adottato dalle reti neurali rispetto al rigido e rassicurante mondo del codice tradizionale. Proprio per questa ragione ho deciso di raccogliere la sfida e provare a raccontarvelo.
Per farlo, mi prenderò la libertà di semplificare parecchio alcuni concetti, anche a costo di tralasciare qualche dettaglio tecnico. Il mio scopo principale è offrirvi una prima intuizione su come funzionano questi sistemi complessi: senza formule troppe complicate, senza codice troppo complicato, solo con calcoli semplici e qualche grafico di aiuto. Spero che, alla fine della lettura, vi rimanga almeno un’idea, anche se non perfetta, di cosa sia e come operi una rete neurale.
Prima definiamo un obiettivo: vogliamo che il nostro neurone impari una cosa semplicissima, che comprenda il raddoppio di un valore.
Input: 2
Voglio Output: 4Come linguaggio di programmazione usiamo Python perché è quello più usato nelle reti neurali ed inoltre presenta una sintassi semplificata rispetto a linguaggi più complessi come C#, C++ o simili.
# 1. Valori iniziali
peso = 0.5 # parte a caso
bias = 0.0 # parte da zero
learning_rate = 0.1
# 2. Dati di addestramento
x = 2
y_vero = 4
# 3. Previsione iniziale
y_predetto = peso * x + bias
# 4. Calcolo dell'errore
errore = y_predetto - y_vero
# Stampa
print(f"Previsione iniziale: {y_predetto}")
print(f"Errore iniziale: {errore}")
# 5. Calcolo quanto correggere peso e bias
grad_peso = errore * x
grad_bias = errore
# 6. Aggiornamento peso e bias
peso = peso - learning_rate * grad_peso
bias = bias - learning_rate * grad_bias
print(f"Peso aggiornato: {peso}")
print(f"Bias aggiornato: {bias}")
# 7. Nuova previsione
y_predetto = peso * x + bias
print(f"Nuova previsione: {y_predetto}")
# Vediamo l'errore aggiornato
errore = y_predetto - y_vero
print(f"Nuovo errore: {errore}")Leggiamo i numeri in uscita, verranno stampati in console dalla funzione print(), per seguire sotituite i numeri nel codice. Questa serie di calcoli, seppur semplice, permette di ridurre l’errore della metà ogni volta che viene corretto peso e bias.
Previsione iniziale: 1.0
Errore iniziale: -3.0
Peso aggiornato: 1.1
Bias aggiornato: 0.30000000000000004
Nuova previsione: 2.5
Nuovo errore: -1.5- Iniziamo con un peso e bias scelti a caso.
- Dati di addestramento, senza addestramento la AI non può funzionare.
- Prevediamo: moltiplichiamo peso * input + bias.
- Calcoliamo l’errore: differenza tra il valore predetto (y_predetto) e quello vero (y_vero).
- Calcoliamo di quanto correggere: l’errore ci dice la direzione e quanto correggere.
- Aggiorniamo il peso e il bias: sottraiamo una piccola parte dell’errore (learning_rate*).
- Ripetiamo: vediamo che la previsione migliora, l’errore è stato dimezzato, da -3.0 a -1.5
Proviamo con 10 passi
Più passaggi ripetuti porteranno una riduzione progressiva dell’errore fino ad avvicinarlo abbastanza dallo zero da poterlo considerare trascurabile. Nel codice seguente aggiungiamo un ciclo for che effettuerà 10 passate.
Useremo inoltre la libreria Pandas per Python, popolarissima per la manipolazione dei dati. Ci servirà per istanziare un DataFrame che altro non è che una struttura di dati bidimensionale simile a una tabella di Excel, che permette di organizzare e manipolare dati in righe e colonne. Per i programmatori possiamo dire che il DataFrame gira molto più veloce di una normale Matrice 2D creata in Python “puro”. Se seguite il flusso del codice memorizziamo prima i dati con un append nella variabile pesos per poi, al termine del ciclo, inserirla nella tabella DataFrame in “Peso”: pesos…
Per semplificare ancora di più il codice ci appoggeremo alla libreria ace_tools per il rendering in console del DataFrame, vedi: tools.display_dataframe_to_user…
# Reinizializziamo
peso = 0.5
bias = 0.0
learning_rate = 0.1
x = 2
y_vero = 4
# Salviamo i valori per ogni passo
pesos = []
biases = []
predizioni = []
errori = []
# Facciamo 10 passi di aggiornamento e salviamo nella variabile con un append
for passo in range(10):
y_predetto = peso * x + bias
errore = y_predetto - y_vero
grad_peso = errore * x
grad_bias = errore
peso -= learning_rate * grad_peso
bias -= learning_rate * grad_bias
pesos.append(peso)
biases.append(bias)
predizioni.append(y_predetto)
errori.append(errore)
# Visualizziamo i risultati
import pandas as pd
# 1. Organiziiamo in un DataFrame
tabella = pd.DataFrame({
"Passo": range(1, 11),
"Peso": pesos,
"Bias": biases,
"Predizione": predizioni,
"Errore": errori
})
# 2. Renderizziamo a video
import ace_tools as tools; tools.display_dataframe_to_user(name="Aggiornamenti del Neurone", dataframe=tabella)Ecco il risultato in console, il rendering dei dati prodotti
Passo Peso Bias Predizione Errore
0 1 1.100000 0.300000 1.000000 -3.000000
1 2 1.400000 0.450000 2.500000 -1.500000
2 3 1.550000 0.525000 3.250000 -0.750000
3 4 1.625000 0.562500 3.625000 -0.375000
4 5 1.662500 0.581250 3.812500 -0.187500
5 6 1.681250 0.590625 3.906250 -0.093750
6 7 1.690625 0.595313 3.953125 -0.046875
7 8 1.695312 0.597656 3.976562 -0.023438
8 9 1.697656 0.598828 3.988281 -0.011719
9 10 1.698828 0.599414 3.994141 -0.005859Vedrai passo dopo passo come:
- Il peso e il bias si aggiornano.
- La predizione si avvicina sempre più al valore corretto (4).
- L’errore diventa sempre più piccolo, si dimezza ad ogni passo.

Ogni punto rappresenta un aggiornamento del neurone, e vedi chiaramente che l’errore si avvicina rapidamente a zero.
Questo è esattamente il principio di base con cui funzionano le reti neurali: provano, misurano l’errore, e migliorano passo dopo passo! Non si arriverà mai esattamente ad errore uguale a zero (convergenza asintotica), ma si può arrivare a un errore così piccolo da considerarlo praticamente zero.
Come facciamo a calcolare quando l’errore scenderà ad esempio sotto la soglia di 0.001? Supponendo sia il nostro obiettivo ovviamente. Aiutiamoci con un altro script Python, questa volta sfruttiamo la libreria math che ci permette di gestire i calcoli matematici, in questo caso logaritmici.
import math
# Errore iniziale
errore_iniziale = 3.0
# Soglia di errore desiderata
soglia = 0.001
# Calcolo il numero di passaggi necessari
# Supponiamo che l'errore si dimezzi a ogni passo (fattore di riduzione di circa 0.5)
numero_passi = math.ceil(math.log2(errore_iniziale / soglia))
print(numero_passi)
# il risultato sarà 12In conclusione 12 cicli for per raggiungere la soglia di errore pari a 0.001
Cos’è il Learning Rate?
Il learning rate decide quanto grande è ogni passo che fa il neurone per correggersi:
- Learning rate grande (
0.5o1.0): passi grandi → apprende più in fretta, ma può saltare il minimo! - Learning rate piccolo (
0.01o0.001): passi piccoli → apprende lentamente, ma è più stabile.
| Learning Rate | Numero di Passi per Errore < 0.001 |
|---|---|
| 0.01 | 397 passi (molto lento) |
| 0.1 | 36 passi (molto buono) |
| 0.5 | 1 passo! (ma attenzione: è rischioso, può saltare il minimo in problemi più complicati) |

- Learning rate 0.01: l’errore scende lentissimo.
- Learning rate 0.1: scende velocemente e stabilmente.
- Learning rate 0.5: scende in un solo passo!
Già da questo esempio potete capire come sia complicato addestrare una AI e quante risorse di calcolo richieda. Se abbiamo dovuto affrontare tutti questi ragionamenti per risolvere il nostro semplice caso, immaginate come deve essere complicato gestire l’addestramento con miliardi di token e miliardi di connessioni… si procede a tentativi, controllati, ma pur sempre di tentativi tratta. Più dati si utilizzano, migliore è la loro qualità, migliore sono le strategie di addestramento, più preciso sarà il risultato o meglio, sarò maggiormente mitigato il rischio di errore.
Grazie per aver letto fino in fondo questo articolo, se ti è piaciuto restiamo in contatto su linkedin a https://www.linkedin.com/in/andreatonin/
Nerd per passione e per professione da oltre 30 anni, lavoro nel mondo dell’innovazione tecnologica come CTO e consulente, progettando ecosistemi software complessi e scalabili. Parallelamente mi dedico alla formazione informatica, condividendo esperienze e buone pratiche maturate sul campo.
Scopri di più sulla mia attività di consulenza su lucedigitale.com Mi trovi anche su LinkedIn

















