Vai al contenuto principale
Teorema di Bayes - immagine ufficiale della lezione su GinnyTech, creata da AD

Teorema di Bayes e aggiornamento delle credenze

Come il teorema di Bayes formalizza l'apprendimento dai dati in ogni decisione analitica.

AD
Creato daAndrii Dyshkantiuk
Lezione 154 / 236Livello: AvanzatoDurata: 22 minPrerequisiti: 1

Cosa imparerai

  • Calcolare il posterior con il teorema di Bayes a partire da prior, likelihood ed evidenza
  • Aggiornare una credenza a ogni nuova evidenza usando il posterior come prior successivo
  • Interpretare la probabilità del segnale senza confonderla con la probabilità della causa

Teorema di Bayes e aggiornamento delle credenze

Questa lezione vive nel binario ml-tabellare, dove ogni aggiornamento parte da una tabella di transazioni. Bayes è il linguaggio dell’aggiornamento disciplinato. Parti da quello che sapevi prima, osservi una nuova evidenza e cambi giudizio senza farti dominare né dall’istinto né dal singolo dato rumoroso. Prendi un alert antifrode che segnala una transazione come sospetta: il modello ha una precisione apparentemente alta, ma il fenomeno è raro e la maggior parte dei casi segnalati potrebbe comunque essere innocente.

Che cosa fa Bayes, in una frase

Il teorema di Bayes aggiorna in modo disciplinato quanto credi a un’ipotesi dopo aver osservato una nuova evidenza.

Come si aggiorna una credenza

  1. Dichiara l’ipotesi H e stima il prior P(H) da dati storici o baseline note.
  2. Stima la likelihood P(D|H), cioè quanto sono probabili i dati osservati se l’ipotesi è vera.
  3. Calcola l’evidenza P(D) come media delle likelihood pesata su tutte le ipotesi.
  4. Applica Bayes con P(H|D) = P(D|H) × P(H) / P(D) per ottenere il posterior.
  5. Ripeti l’aggiornamento a ogni nuova evidenza, usando il posterior di oggi come prior di domani.
  6. Confronta il posterior con una soglia decisionale scritta prima dell’analisi e agisci solo oltre soglia.

Anatomia del teorema

Posterior = Likelihood × Prior / Evidence

P(H|D) = P(D|H) × P(H) / P(D)

Il prior P(H) è cosa credevi prima di vedere i dati. Non è un pregiudizio: è la sintesi di tutta l’informazione precedente. La likelihood P(D|H) misura quanto sono probabili i dati osservati se l’ipotesi è vera. L’evidence P(D) è la probabilità marginale dei dati, cioè la costante di normalizzazione. Il posterior P(H|D) è cosa credi dopo aver visto i dati.

Il punto chiave è non confondere la probabilità del segnale con la probabilità della causa. Molti errori analitici nascono quando P(evidenza | ipotesi) viene scambiata per P(ipotesi | evidenza).

Applicazione all’analisi dati

Torniamo al rilevamento frodi. Una transazione arriva dalla Nigeria alle 3 AM per 8.500€. Qual è la probabilità che sia fraudolenta?

  • Prior: P(frode) = 0.001, cioè lo 0,1% delle transazioni
  • Likelihood: P(Nigeria, 3AM, >5000€ | frode) = 0.25
  • Likelihood: P(Nigeria, 3AM, >5000€ | non_frode) = 0.0001
  • Evidence: P(D) = 0.25×0.001 + 0.0001×0.999 = 0.00035

Posterior: P(frode | D) = 0.25 × 0.001 / 0.00035 ≈ 0.714 = 71.4%

La probabilità di frode passa da 0,1% a 71% con tre osservazioni. Questo è il meccanismo che alimenta i sistemi di fraud detection in tempo reale.

Bayesian A/B testing

Invece di un valore p puntuale, il bayesian A/B testing produce una distribuzione di probabilità sull’effetto. Se la distribuzione dell’effetto ha il 95% della massa sopra lo zero, puoi dire che c’è una probabilità del 95% che B sia migliore di A.

Matematicamente assumi un prior sull’effetto, per esempio una normale con media 0, combini i dati del test per calcolare la posterior e guardi l’area sotto la curva sopra la soglia di rilevanza pratica. Questo è esattamente ciò che un analyst vuole sapere, e che il valore p non può dire.

Verdetto: usa la lettura bayesiana quando devi decidere sotto incertezza con un prior difendibile, quella frequentista quando servono garanzie di errore a lungo termine, e non mescolare le due letture nello stesso report.

Riferimenti:

  • Graham, P. (2002). “A Plan for Spam.” paulgraham.com.
  • Kruschke, J.K. (2014). Doing Bayesian Data Analysis, 2nd ed. Academic Press.

Esempio SQL: costruire una vista di controllo

La vista seguente crea una base analitica con metrica, segmento e finestra temporale, così puoi confrontare periodi e gruppi senza riscrivere la logica ogni volta.

WITH base_events AS (
  SELECT
    user_id,
    account_id,
    event_type,
    event_time,
    DATE_TRUNC('week', event_time) AS week,
    source,
    device_type
  FROM events
  WHERE event_time >= CURRENT_DATE - INTERVAL '180 days'
    AND user_id IS NOT NULL
),
weekly_user_metrics AS (
  SELECT
    week,
    user_id,
    COALESCE(source, 'unknown') AS source,
    COALESCE(device_type, 'unknown') AS device_type,
    COUNT(*) AS total_events,
    COUNT(DISTINCT DATE(event_time)) AS active_days,
    COUNT(DISTINCT event_type) AS event_diversity,
    MAX(CASE WHEN event_type IN ('purchase', 'subscribe', 'activation') THEN 1 ELSE 0 END) AS reached_key_outcome
  FROM base_events
  GROUP BY week, user_id, source, device_type
)
SELECT
  week,
  source,
  device_type,
  COUNT(DISTINCT user_id) AS users,
  ROUND(AVG(active_days), 2) AS avg_active_days,
  ROUND(AVG(event_diversity), 2) AS avg_event_diversity,
  ROUND(AVG(reached_key_outcome) * 100, 2) AS key_outcome_rate
FROM weekly_user_metrics
GROUP BY week, source, device_type
ORDER BY week, source, device_type;

Esempio Python: controllare stabilità e anomalie

Il controllo seguente segnala variazioni anomale settimana su settimana senza reagire a ogni oscillazione casuale.


# df contiene: week, segment, users, key_outcome_rate
# key_outcome_rate espresso in percentuale, es. 12.4

df = df.sort_values(['segment', 'week']).copy()
df['previous_rate'] = df.groupby('segment')['key_outcome_rate'].shift(1)
df['wow_change_pp'] = df['key_outcome_rate'] - df['previous_rate']
df['rolling_mean'] = df.groupby('segment')['key_outcome_rate'].transform(
    lambda s: s.rolling(4, min_periods=2).mean()
)
df['rolling_std'] = df.groupby('segment')['key_outcome_rate'].transform(
    lambda s: s.rolling(4, min_periods=2).std()
)
df['z_score'] = (df['key_outcome_rate'] - df['rolling_mean']) / df['rolling_std']

anomalies = df[df['z_score'].abs() >= 2].sort_values('z_score')
print(anomalies[['week', 'segment', 'key_outcome_rate', 'wow_change_pp', 'z_score']])

Paul Graham e il filtro antispam bayesiano

Nel 2002 Paul Graham pubblicò “A Plan for Spam”, il saggio che introdusse il filtro antispam bayesiano. L’idea era semplice: ogni parola di una email contribuisce con un peso di spam basato sulla frequenza storica, e il classificatore combina i pesi delle parole più informative usando il teorema di Bayes per produrre una probabilità finale. Il sistema migliorava da solo, perché ogni nuova email marcata come spam o non spam aggiornava le probabilità di partenza. Quel meccanismo di aggiornamento continuo è rimasto il riferimento pratico del bayesian updating in produzione.

Domande per chiudere la lezione

  1. Perché un modello con accuratezza del 99% può essere inutile su un fenomeno raro?
  2. Quando il prior domina il posterior e cosa fai in quel caso?
  3. Come distingui la probabilità del segnale dalla probabilità della causa in un alert?
  4. Quale controllo fai prima di usare un posterior bayesiano per bloccare un utente?
Serve una mano concreta?

Bloccato su questo argomento o vuoi applicarlo al tuo caso? Prenota una call di 15 minuti con un analista esperto.

Prenota una call