statistica

L’algoritmo di Discesa del Gradiente spiegato in modo chiaro: dall’intuizione alla pratica

Una persona bendata su una montagna

Immagina di trovarti su un terreno montagnoso, completamente bendato. Il tuo obiettivo: raggiungere il punto più basso della valle. Non puoi vedere nulla, ma puoi sentire la pendenza del terreno sotto i piedi. Cosa fai? Ti muovi nella direzione in cui il terreno scende, un passo alla volta. Se scende più ripidamente a sinistra, vai a sinistra. Se scende di più a destra, vai a destra. Ad ogni passo, senti di nuovo la pendenza e cambi direzione.

Questa strategia, così semplice e naturale, è esattamente quella che le reti neurali usano per imparare. Ogni volta che un modello di intelligenza artificiale migliora — che impari a riconoscere un volto, tradurre una frase, o generare un testo — lo fa scendendo lungo un paesaggio matematico, un passo alla volta, seguendo la pendenza.

Si chiama discesa del gradiente (gradient descent), ed è probabilmente l’algoritmo più importante del machine learning moderno.

Da Cauchy alle reti neurali: una breve storia

L’idea di seguire la pendenza per trovare un minimo ha radici sorprendentemente antiche. Nel 1847, il matematico francese Augustin-Louis Cauchy pubblica un metodo per risolvere sistemi di equazioni che, nella sostanza, è già la discesa del gradiente: calcolare la direzione di massima crescita di una funzione e muoversi nella direzione opposta. Cauchy non pensava alle reti neurali — mancava più di un secolo alla loro comparsa — ma aveva formalizzato il principio che ancora oggi alimenta l’intelligenza artificiale.

Per oltre un secolo l’idea resta confinata alla matematica pura. La svolta arriva nel 1951, quando Herbert Robbins e Sutton Monro propongono una versione stocastica del metodo: invece di calcolare il gradiente sull’intero problema, lo si stima su un campione casuale. È il seme di quello che oggi chiamiamo Stochastic Gradient Descent (SGD) — ne parleremo nella sezione finale. Pochi anni dopo, nel 1958, Frank Rosenblatt costruisce il perceptron, il primo modello di apprendimento automatico che usa la discesa del gradiente per imparare dai dati. L’entusiasmo è enorme, ma dura poco: nel 1969 Minsky e Papert dimostrano i limiti del perceptron, e l’interesse per le reti neurali crolla. È il cosiddetto inverno dell’intelligenza artificiale.

La rinascita arriva nel 1986, quando David Rumelhart, Geoffrey Hinton e Ronald Williams pubblicano l’algoritmo di backpropagation: un modo efficiente per calcolare il gradiente in reti neurali con molti strati. È la chiave che sblocca il deep learning. Da quel momento, la discesa del gradiente non è più un esercizio teorico ma lo strumento pratico con cui si addestrano le reti neurali. L’ultimo tassello di questa storia lo pongono Diederik Kingma e Jimmy Ba nel 2014, con l’ottimizzatore Adam — che ritroveremo nella sezione finale di questo articolo. Quasi due secoli separano Cauchy da Adam, eppure il principio è rimasto lo stesso: senti la pendenza, fai un passo nella direzione opposta.

La matematica, spiegata geometricamente

La funzione di costo: misurare quanto sbaglia il modello

Prima di scendere, dobbiamo sapere cosa stiamo minimizzando. La persona bendata cerca il punto più basso della valle — ma nel machine learning, cos’è esattamente quella valle?

Facciamo un esempio concreto. Supponiamo di voler prevedere il prezzo di una casa conoscendo solo la sua superficie. Abbiamo cinque case di cui conosciamo superficie e prezzo reale, e il nostro modello è il più semplice possibile: una retta che passa per l’origine, prezzo = m × superficie, dove m è l’unico parametro da regolare.

Per ogni valore di m, il modello fa una previsione. Se m è troppo basso, le previsioni sottostimano i prezzi reali; se è troppo alto, li sovrastimano. Abbiamo bisogno di un numero che ci dica quanto il modello sta sbagliando: è la funzione di costo (o loss function, come dicono gli anglosassoni).

La funzione di costo più usata è l’errore quadratico medio (MSE, Mean Squared Error): per ogni casa, calcoliamo la differenza tra il prezzo previsto e quello reale, la eleviamo al quadrato, e facciamo la media di tutti questi errori. In formula:

MSE(m) = (1/n) ∑i (prezzoi − m × superficiei

Se plottiamo MSE(m) al variare di m, otteniamo una curva a forma di parabola: la stessa parabola che useremo tra poco come esempio della discesa del gradiente. Non è una coincidenza — la parabola è la funzione di costo, e il suo punto più basso è il valore di m che rende il modello migliore possibile.

Gli esempi che seguono sono disponibili sia in R che in Python — ognuno segua il linguaggio con cui ha più familiarità.

Calcoliamo in R la funzione di costo per il nostro esempio delle case:

# Funzione di costo: prevedere il prezzo di una casa
superficie <- c(50, 70, 90, 120, 150)
prezzo <- c(150, 200, 260, 340, 400)  # migliaia di euro

# Modello: prezzo = m * superficie
# Funzione di costo MSE al variare di m
m_valori <- seq(1, 4, by = 0.01)
mse <- sapply(m_valori, function(m) mean((prezzo - m * superficie)^2))

plot(m_valori, mse, type = "l", lwd = 2, col = "steelblue",
     xlab = "m (pendenza)", ylab = "MSE",
     main = "Funzione di costo al variare di m")
m_ottimo <- m_valori[which.min(mse)]
abline(v = m_ottimo, col = "red", lty = 2)
cat("Il valore di m che minimizza l'errore:", round(m_ottimo, 2), "\n")

Verifichiamo in Python:

import numpy as np
import matplotlib.pyplot as plt

# Funzione di costo: prevedere il prezzo di una casa
superficie = np.array([50, 70, 90, 120, 150])
prezzo = np.array([150, 200, 260, 340, 400])  # migliaia di euro

# Modello: prezzo = m * superficie
# Funzione di costo MSE al variare di m
m_valori = np.linspace(1, 4, 301)  # equivalente a seq(1, 4, by=0.01) in R
mse = np.array([np.mean((prezzo - m * superficie)**2) for m in m_valori])

plt.plot(m_valori, mse, lw=2, color="steelblue")
plt.xlabel("m (pendenza)")
plt.ylabel("MSE")
plt.title("Funzione di costo al variare di m")
m_ottimo = m_valori[np.argmin(mse)]
plt.axvline(m_ottimo, color="red", linestyle="--")
plt.show()
print(f"Il valore di m che minimizza l'errore: {m_ottimo:.2f}")

Ora sappiamo cosa minimizzare: la funzione di costo. Il gradiente ci dice come.

Derivata: la pendenza sotto i piedi

Quando hai una funzione di una sola variabile — pensala come un sentiero che sale e scende — la derivata in un punto ti dice quanto è ripido il sentiero in quel punto. Se la derivata è positiva, stai salendo. Se è negativa, stai scendendo. Se è zero, sei su un tratto piatto: forse una cima, forse un avvallamento.

Esempio concreto: la funzione f(x) = x² descrive una parabola. La sua derivata è f'(x) = 2x. Se sei nel punto x = 3, la derivata vale 6: stai salendo ripidamente. Se sei in x = -1, la derivata vale -2: stai scendendo. In x = 0, la derivata è zero: sei nel punto più basso.

Il gradiente: una bussola multidimensionale

Nella realtà, le funzioni che ci interessano non dipendono da una sola variabile. Un modello di machine learning può avere centinaia, migliaia, o miliardi di parametri. Il paesaggio non è più un sentiero, ma una superficie in uno spazio a molte dimensioni — impossibile da visualizzare, ma perfettamente gestibile dalla matematica.

Il gradiente è il vettore che raccoglie tutte le derivate parziali della funzione rispetto a ciascun parametro. Se la funzione dipende da due variabili (x, y), il gradiente è:

∇f = (∂f/∂x, ∂f/∂y)

Se dipende da mille variabili, il gradiente è un vettore con mille componenti. In ogni caso, il gradiente punta nella direzione di massima salita. Per trovare il minimo, basta andare nella direzione opposta: meno il gradiente.

Ecco la formula fondamentale della discesa del gradiente:

θnuovo = θvecchio − α · ∇f(θ)

Smontiamola pezzo per pezzo:

  • θ rappresenta i parametri del modello — le “manopole” che l’algoritmo regola per migliorare
  • ∇f(θ) è il gradiente: indica la direzione di massima salita nel punto attuale
  • α (alpha) è il learning rate: la dimensione del passo che facciamo ad ogni iterazione
  • Il segno meno ci fa andare nella direzione opposta al gradiente, cioè in discesa

È tutto qui. Calcola dove stai salendo, fai un passo nella direzione opposta, ripeti.

Un esempio numerico in R

Vediamo la discesa del gradiente in azione sulla funzione f(x) = x². Sappiamo che il minimo è in x = 0. L’algoritmo riesce a trovarlo partendo da un punto casuale?

# Discesa del gradiente su f(x) = x^2
# La derivata e' f'(x) = 2x

f <- function(x) x^2         # funzione obiettivo
grad_f <- function(x) 2 * x  # derivata (gradiente in 1D)

x <- 10              # punto di partenza
alpha <- 0.1          # learning rate
n_iter <- 50          # numero di iterazioni
percorso <- numeric(n_iter)

for (i in 1:n_iter) {
  percorso[i] <- x
  x <- x - alpha * grad_f(x)  # la regola fondamentale
}

cat("Punto di partenza: 10\n")
cat("Dopo 50 iterazioni: x =", round(x, 8), "\n")
cat("Valore della funzione:", round(f(x), 10), "\n")

# Visualizzazione del percorso
curve(x^2, from = -11, to = 11, lwd = 2, col = "steelblue",
      main = "Discesa del gradiente su f(x) = x^2",
      xlab = "x", ylab = "f(x)")
points(percorso, percorso^2, col = "red", pch = 19, cex = 0.7)
lines(percorso, percorso^2, col = "red", lty = 2)

Verifichiamo in Python:

import numpy as np
import matplotlib.pyplot as plt

# Discesa del gradiente su f(x) = x^2
f = lambda x: x**2           # funzione obiettivo
grad_f = lambda x: 2 * x     # derivata (gradiente in 1D)

x = 10.0            # punto di partenza
alpha = 0.1          # learning rate
n_iter = 50          # numero di iterazioni
percorso = np.zeros(n_iter)

for i in range(n_iter):
    percorso[i] = x
    x = x - alpha * grad_f(x)  # la regola fondamentale

print(f"Punto di partenza: 10")
print(f"Dopo 50 iterazioni: x = {x:.8f}")
print(f"Valore della funzione: {f(x):.10f}")

# Visualizzazione del percorso
xs = np.linspace(-11, 11, 200)
plt.plot(xs, xs**2, lw=2, color="steelblue")
plt.plot(percorso, percorso**2, "ro--", markersize=4)
plt.title("Discesa del gradiente su f(x) = x²")
plt.xlabel("x")
plt.ylabel("f(x)")
plt.show()

Eseguendo questo codice, si vede l’algoritmo partire da x = 10 e convergere rapidamente verso x = 0. I primi passi sono grandi (la pendenza è ripida), poi si accorciano man mano che ci avviciniamo al fondo della parabola. Dopo 50 iterazioni, x è praticamente zero.

Il learning rate: passi grandi o passi piccoli?

Torniamo alla nostra persona bendata. Quant’è grande il passo che fa ad ogni iterazione? Questa è esattamente la domanda del learning rate (α), e la risposta è meno banale di quanto sembri.

Passi troppo piccoli (α molto basso): la persona si muove con cautela estrema, spostando un piede di pochi centimetri alla volta. Alla fine arriverà in fondo alla valle, ma potrebbe impiegare un’eternità. Nel machine learning, questo significa tempi di addestramento lunghissimi e costi computazionali elevati.

Passi troppo grandi (α troppo alto): la persona fa balzi enormi. Invece di scendere dolcemente nella valle, la scavalca, finisce dall’altra parte, rimbalza indietro, e continua a oscillare senza mai stabilizzarsi. In casi estremi, i salti diventano sempre più grandi e la persona finisce più in alto di dove era partita. Nel machine learning, questo si chiama divergenza: il modello peggiora invece di migliorare.

Passi giusti: un buon learning rate permette di scendere velocemente senza oscillare. Nella pratica, trovare il valore giusto richiede sperimentazione. È uno degli aspetti più artigianali del machine learning.

Convergenza: sapere quando fermarsi

Come sa la persona bendata di essere arrivata? Sente che il terreno è piatto in tutte le direzioni: il gradiente è (quasi) zero. In pratica, l’algoritmo si ferma quando il miglioramento tra un’iterazione e l’altra diventa trascurabile, o quando ha raggiunto un numero massimo di iterazioni.

I criteri di arresto più comuni sono:

  • La norma del gradiente scende sotto una soglia minima (il terreno è quasi piatto)
  • La differenza tra f(θ) di due iterazioni consecutive è minore di una tolleranza fissata
  • Si è raggiunto il numero massimo di iterazioni (budget computazionale esaurito)

L’effetto del learning rate: un confronto visuale

Questo codice R mostra l’effetto di tre diversi valori di learning rate sulla stessa funzione:

# Confronto di tre learning rate sulla funzione f(x) = x^2
gradient_descent <- function(x0, alpha, n_iter = 30) {
  x <- x0
  percorso <- numeric(n_iter)
  for (i in 1:n_iter) {
    percorso[i] <- x
    x <- x - alpha * 2 * x  # theta_new = theta_old - alpha * grad
  }
  return(percorso)
}

x0 <- 8  # stesso punto di partenza per tutti

# Tre learning rate diversi
lento    <- gradient_descent(x0, alpha = 0.01)   # troppo piccolo
giusto   <- gradient_descent(x0, alpha = 0.1)    # buon compromesso
veloce   <- gradient_descent(x0, alpha = 0.9)    # quasi instabile

# Visualizzazione
par(mfrow = c(1, 3))

# alpha = 0.01 (troppo lento)
curve(x^2, from = -10, to = 10, lwd = 2, col = "steelblue",
      main = expression(paste(alpha, " = 0.01 (troppo lento)")))
points(lento, lento^2, col = "red", pch = 19, cex = 0.6)
lines(lento, lento^2, col = "red", lty = 2)

# alpha = 0.1 (giusto)
curve(x^2, from = -10, to = 10, lwd = 2, col = "steelblue",
      main = expression(paste(alpha, " = 0.1 (buon compromesso)")))
points(giusto, giusto^2, col = "darkgreen", pch = 19, cex = 0.6)
lines(giusto, giusto^2, col = "darkgreen", lty = 2)

# alpha = 0.9 (quasi instabile)
curve(x^2, from = -10, to = 10, lwd = 2, col = "steelblue",
      main = expression(paste(alpha, " = 0.9 (quasi instabile)")))
points(veloce, veloce^2, col = "orange", pch = 19, cex = 0.6)
lines(veloce, veloce^2, col = "orange", lty = 2)

par(mfrow = c(1, 1))

Confrontiamo in Python:

import numpy as np
import matplotlib.pyplot as plt

def gradient_descent(x0, alpha, n_iter=30):
    x = x0
    percorso = np.zeros(n_iter)
    for i in range(n_iter):
        percorso[i] = x
        x = x - alpha * 2 * x  # theta_new = theta_old - alpha * grad
    return percorso

x0 = 8.0  # stesso punto di partenza per tutti
lento  = gradient_descent(x0, alpha=0.01)   # troppo piccolo
giusto = gradient_descent(x0, alpha=0.1)    # buon compromesso
veloce = gradient_descent(x0, alpha=0.9)    # quasi instabile

fig, axes = plt.subplots(1, 3, figsize=(14, 4))
xs = np.linspace(-10, 10, 200)
for ax, dati, colore, titolo in zip(axes,
        [lento, giusto, veloce],
        ["red", "darkgreen", "orange"],
        ["\u03b1 = 0.01 (troppo lento)", "\u03b1 = 0.1 (buon compromesso)",
         "\u03b1 = 0.9 (quasi instabile)"]):
    ax.plot(xs, xs**2, lw=2, color="steelblue")
    ax.plot(dati, dati**2, "o--", color=colore, markersize=4)
    ax.set_title(titolo)
plt.tight_layout()
plt.show()

Con α = 0.01 i punti rossi si muovono pigramente: dopo 30 iterazioni siamo ancora lontani dal minimo. Con α = 0.1 la convergenza è rapida e pulita. Con α = 0.9 l’algoritmo oscilla vistosamente a ogni passo, rimbalzando da un lato all’altro della parabola prima di stabilizzarsi — un learning rate appena più alto e divergerebbe del tutto.

Cosa può andare storto: l’intuizione geometrica

Il paesaggio matematico di un modello reale non è una bella parabola simmetrica. È un terreno selvaggio, con valli secondarie, creste, altipiani e forme che sfidano l’immaginazione. Ecco i problemi classici, spiegati con l’analogia del paesaggio.

Minimi locali: le valli secondarie

Immagina un terreno con più avvallamenti: una valle profonda (il minimo globale) e diverse vallette meno profonde (i minimi locali). La persona bendata non ha modo di sapere se la valle in cui si trova è quella più profonda. Sente il terreno piatto sotto i piedi e si ferma, convinta di essere arrivata. Ma potrebbe trovarsi in una valletta poco profonda, mentre il vero minimo è da tutt’altra parte.

Nella pratica, questo è un problema meno grave di quanto si pensasse. Le reti neurali moderne hanno così tanti parametri che i minimi locali tendono ad avere valori della funzione obiettivo simili al minimo globale. È come un terreno con molte valli, ma tutte più o meno alla stessa altitudine: finire in una qualsiasi va bene.

Punti di sella: la sella di cavallo

Un problema più insidioso sono i punti di sella (saddle points). Immagina di essere seduto su una sella di cavallo: se ti muovi avanti o indietro, scendi; se ti muovi a destra o sinistra, sali. In quel punto il gradiente è zero — il terreno sembra piatto — ma non sei in un minimo. Sei su un punto che è minimo in alcune direzioni e massimo in altre.

In spazi ad alta dimensionalità, i punti di sella sono molto più comuni dei minimi locali. Fortunatamente, le varianti moderne della discesa del gradiente (con un po’ di rumore o di momentum, come vedremo) riescono generalmente a sfuggire ai punti di sella.

Valli strette: lo zigzag

Immagina una valle molto stretta e allungata, come un canyon. Il gradiente punta quasi perpendicolarmente alle pareti del canyon, non lungo il canyon verso il fondo. La persona bendata finisce per rimbalzare da una parete all’altra, facendo uno zigzag inefficiente invece di camminare dritta verso il fondo.

Questo accade quando le variabili del problema hanno scale molto diverse: alcune cambiano rapidamente, altre lentamente. È un problema comune nella pratica, e una delle motivazioni principali per gli ottimizzatori avanzati come Adam, che vedremo nella sezione finale.

Da una parabola a ChatGPT

Finora abbiamo visto la discesa del gradiente su una parabola: un problema con una sola variabile. È il caso più semplice possibile. Ma il bello di questo algoritmo è che funziona esattamente allo stesso modo a qualsiasi scala.

La scala dei parametri

Ecco come cresce il numero di parametri man mano che i modelli diventano più complessi:

  • Regressione lineare semplice: 2 parametri (pendenza e intercetta). Il paesaggio è una superficie 3D facile da visualizzare.
  • Rete neurale per riconoscere cifre scritte a mano: ~100.000 parametri. Il paesaggio ha 100.000 dimensioni.
  • ResNet-50 (classificazione immagini, 2015): ~25 milioni di parametri.
  • GPT-3 (il predecessore di ChatGPT): 175 miliardi di parametri.
  • GPT-4 e modelli di frontiera (2023-2025): si stima oltre un trilione di parametri.

Il principio è identico: calcola il gradiente, fai un passo nella direzione opposta, ripeti. Quello che cambia è la scala del calcolo. Il gradiente di GPT-4 è un vettore con più di mille miliardi di componenti, calcolato su miliardi di frammenti di testo, usando migliaia di processori in parallelo. Ma la formula è la stessa che abbiamo visto sulla parabola.

Dove lo vedi in azione (senza saperlo)

Ogni volta che interagisci con un sistema di intelligenza artificiale, la discesa del gradiente ha lavorato dietro le quinte:

  • Netflix e Spotify che ti consigliano cosa guardare o ascoltare: i modelli di raccomandazione sono addestrati con gradient descent su miliardi di interazioni utente
  • Google Translate e i traduttori automatici: reti neurali con centinaia di milioni di parametri, ottimizzate con discesa del gradiente su enormi corpora di testi paralleli
  • Assistenti vocali (Siri, Alexa): il riconoscimento vocale usa reti neurali profonde, addestrate con lo stesso algoritmo
  • Guida autonoma: le reti che riconoscono pedoni, semafori e corsie stradali sono addestrate con varianti della discesa del gradiente
  • ChatGPT, Claude, Gemini: i Large Language Model sono il caso più estremo — la discesa del gradiente applicata a miliardi di parametri su trilioni di token di testo

Il messaggio chiave è questo: la potenza dell’AI moderna non sta nella complessità dell’algoritmo di ottimizzazione, ma nella scala. La discesa del gradiente è concettualmente semplice. Quello che ha reso possibile la rivoluzione dell’intelligenza artificiale è la capacità di applicarlo a modelli enormi su quantità enormi di dati, grazie a hardware sempre più potente.

Le evoluzioni: scarpe migliori per il nostro esploratore

La discesa del gradiente “vanilla” — quella che abbiamo visto finora — funziona, ma ha i limiti che abbiamo descritto: può essere lenta, può oscillare, può restare bloccata. Nel corso degli anni, i ricercatori hanno sviluppato varianti che risolvono questi problemi. Senza entrare nelle formule, ecco le idee chiave.

Stochastic Gradient Descent (SGD)

Invece di calcolare il gradiente sull’intero dataset ad ogni passo (computazionalmente costosissimo), SGD lo calcola su un piccolo campione casuale (mini-batch). È come se la persona bendata, invece di tastare l’intero terreno intorno a sé, tastasse solo qualche punto a caso. La stima della pendenza è rumorosa, ma mediamente corretta, e la velocità di calcolo è enormemente maggiore. Il rumore, paradossalmente, è anche utile: aiuta a sfuggire ai minimi locali e ai punti di sella.

Momentum

Immagina una palla che rotola giù per la collina invece di una persona che cammina. La palla accumula velocità: se la pendenza continua nella stessa direzione, accelera. Se la pendenza cambia direzione, la palla rallenta prima di invertire. Questo è il momentum: l’algoritmo “ricorda” la direzione in cui si stava muovendo e ci aggiunge il gradiente attuale. Il risultato è che attraversa più velocemente le zone piatte e oscilla meno nelle valli strette.

Adam: il coltellino svizzero

Adam (Adaptive Moment Estimation) combina l’idea del momentum con un learning rate che si adatta automaticamente per ogni parametro. I parametri che cambiano poco ottengono passi più grandi; quelli che cambiano molto ottengono passi più piccoli. È come se la persona bendata avesse scarpe intelligenti che regolano la lunghezza del passo in base al terreno sotto ogni piede.

Adam è diventato lo standard de facto per addestrare la maggior parte delle reti neurali moderne. È robusto, richiede poca regolazione manuale, e funziona bene in una vasta gamma di problemi. Quasi tutti i modelli che usi quotidianamente — da Spotify a ChatGPT — sono stati addestrati con Adam o con una sua variante.

Ritorno alla montagna

La persona bendata da cui siamo partiti ora ha scarpe migliori. Ha una palla che accumula velocità invece di gambe che fanno passi rigidi. Ha suole che si adattano automaticamente al terreno. E soprattutto, non cammina su una montagna con due o tre dimensioni: cammina su un paesaggio con miliardi di dimensioni.

Ma il principio è esattamente lo stesso. Senti la pendenza. Fai un passo nella direzione in cui scende. Ripeti.

La discesa del gradiente non è un algoritmo spettacolare. Non ha la complessità elegante di un algoritmo genetico o il fascino narrativo delle reti adversariali. È una procedura meccanica, quasi banale. Ma è la procedura meccanica su cui si regge l’intera rivoluzione dell’intelligenza artificiale. Dai suggerimenti di Netflix ai modelli che generano immagini, dalla guida autonoma alla traduzione simultanea, tutto si riduce a questo: una funzione da minimizzare, un gradiente da calcolare, un passo da fare.

La prossima volta che un assistente vocale capisce la tua domanda, o che un traduttore automatico indovina una sfumatura, ricorda: dietro le quinte, una versione molto sofisticata della nostra persona bendata ha camminato per miliardi di passi su un paesaggio con miliardi di dimensioni. E ha trovato una valle abbastanza profonda da essere utile.

paolo

Recent Posts

Calcolatore Sample Size per A/B Test

Una delle domande più ricorrenti quando si progetta un A/B test è: quanti utenti mi…

2 settimane ago

Anomaly detection: come identificare valori anomali nei dati

Tre metodi statistici per identificare valori anomali nei dati: z-score, IQR di Tukey e test…

3 settimane ago

Statistica bayesiana: come imparare dai dati, un passo alla volta

Abbiamo avuto modo di esaminare, nel corso dei precedenti articoli, l'inferenza statistica da una prospettiva…

3 settimane ago

A/B Testing: come condurre esperimenti statisticamente validi (e gli errori da evitare)

Abbiamo avuto modo di esaminare, nel corso dei precedenti articoli, come funziona il test delle…

4 settimane ago

Il Teorema del Limite Centrale: perché la statistica funziona (anche quando i dati non sono normali)

Abbiamo avuto modo di esaminare, nel corso dei precedenti articoli, la distribuzione normale e le…

4 settimane ago

Intervalli di confidenza: cosa sono, come calcolarli (e cosa NON significano)

Abbiamo avuto modo di esaminare, nel corso dei precedenti articoli, come funziona il test delle…

4 settimane ago