TLDR

  • La vera abilità ingegneristica consiste nel diagnosticare scientificamente se un modello soffre di Alto Bias (Underfitting) o Alta Varianza (Overfitting).
  • Le Learning Curves tracciano l'andamento degli errori di Train e Cross-Validation all'aumentare della dimensione del dataset.
  • Nei dataset sbilanciati l'accuratezza classica è ingannevole: Precision, Recall e F1-Score guidano la calibrazione della soglia.
  • Gli alberi decisionali massimizzano l'Information Gain calcolato tramite l'Entropia di Shannon; XGBoost combina alberi sequenziali per correggere i residui.

La Diagnostica Scientifica nei Progetti di Machine Learning

Costruire un'architettura di Machine Learning è solo il primo passo. Quando il modello produce predizioni insoddisfacenti, la differenza tra un principiante e un ingegnere esperto risiede nel metodo di diagnosi: procedere per tentativi casuali o applicare una diagnostica sistematica basata su metriche ed evidenze empiriche.

                  ┌───────────────────────────────┐
                  │ 1. Train Set (60%)           │ ──► Addestramento pesi (w, b)
                  └───────────────────────────────┘
                  ┌───────────────────────────────┐
                  │ 2. Cross-Validation Set (20%) │ ──► Scelta iperparametri (λ, depth)
                  └───────────────────────────────┘
                  ┌───────────────────────────────┐
                  │ 3. Test Set (20%)             │ ──► Stima imparziale generalizzazione
                  └───────────────────────────────┘
🎧 Podcast: Come l'IA impara dai suoi errori Analisi audio su strategie di progetto, diagnosi di bias/varianza e metodi di insieme.

Diagnosi di Bias vs Varianza tramite Learning Curves

Per comprendere la causa primaria delle scarse prestazioni, misuriamo l'errore di addestramento $J_{\text{train}}$ e l'errore di convalida $J_{\text{cv}}$ al variare del numero di campioni $m$ (Learning Curves):

Curva di trade-off tra Bias elevato e Varianza elevata
Diagnosi comparativa: Underfitting (High Bias) vs Fitting Ottimale vs Overfitting (High Variance).

1. Alto Bias (Underfitting)

  • Sintomo: $J_{\text{train}}$ è elevato e $J_{\text{cv}} \approx J_{\text{train}}$ (entrambi ben al di sopra dell'errore accettabile).
  • Causa: Il modello è troppo rigido e non ha sufficiente capacità espressiva per catturare il fenomeno.
  • Cosa NON fare: Raccogliere ulteriori dati (le curve si sono già appiattite; aggiungere campioni non abbasserà l'errore).
  • Azioni Correttive Efficaci:
    • Aumentare la complessità del modello (aggiungere feature polinomiali o strati neurali);
    • Ridurre il parametro di regolarizzazione $\lambda$.

2. Alta Varianza (Overfitting)

  • Sintomo: $J_{\text{train}}$ è bassissimo, ma esiste un ampio divario (gap) con $J_{\text{cv}}$, che risulta molto elevato.
  • Causa: Il modello ha memorizzato il rumore stocastico del set di training senza apprendere la regola generale.
  • Azioni Correttive Efficaci:
    • Raccogliere più dati di addestramento (diminuisce il gap tra train e cross-validation);
    • Selezionare o eliminare feature non discriminanti;
    • Aumentare il parametro di regolarizzazione $\lambda$.

Metriche per Dataset Sbilanciati: Precision, Recall e F1-Score

Nei problemi reali di cybersecurity (es. rilevamento intrusioni su 1 milione di pacchetti con solo 100 attacchi), l'accuratezza classica è un'illusione: un modello banale che predice sempre $0$ (traffico lecito) ottiene un'accuratezza del $99.99%$, pur essendo totalmente inutile.

Definiamo la Matrice di Confusione:

  • True Positive ($TP$): Attacco reale correttamente bloccato;
  • False Positive ($FP$): Traffico lecito erroneamente segnalato come attacco (falso allarme);
  • False Negative ($FN$): Attacco reale non rilevato che oltrepassa le difese;
  • True Negative ($TN$): Traffico lecito correttamente autorizzato.

$$\text{Precision} = \frac{TP}{TP + FP} \quad \text{(Tra tutti i casi predetti come positivi, quanti lo erano davvero?)}$$

$$\text{Recall} = \frac{TP}{TP + FN} \quad \text{(Tra tutti i casi realmente positivi, quanti ne abbiamo intercettati?)}$$

$$\mathbf{F_1\text{-Score}} = 2 \cdot \frac{\text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}} \quad \text{(Media armonica di Precision e Recall)}$$

Modificando la soglia decisionale di classificazione (es. abbassando la soglia da $0.5$ a $0.2$), aumentiamo la Recall (intercettiamo più attacchi) al prezzo di ridurre la Precision (più falsi allarmi). L'indice $F_1$ misura l'equilibrio ottimale di questo trade-off.


Alberi Decisionali ed Entropia di Shannon

Gli Alberi Decisionali costruiscono modelli predittivi gerarchici suddividendo ricorsivamente lo spazio campionario in sottoinsiemi sempre più omogenei (puri).

Struttura di un albero decisionale e calcolo dell'Information Gain
Anatomia dell'albero: Root Node, split su feature e Leaf Nodes con calcolo della purezza.

Misura dell'Impurità: Entropia di Shannon

Dato un nodo con frazione $p_1$ di esempi appartenenti alla classe 1, l'Entropia di Shannon misura il disordine informativo:

$$H(p_1) = -p_1 \log_2(p_1) - (1 - p_1) \log_2(1 - p_1)$$

  • Se $p_1 = 1$ oppure $p_1 = 0$ (nodo perfettamente puro), $H(p_1) = 0$.
  • Se $p_1 = 0.5$ (massima incertezza, 50% classe 1 e 50% classe 0), $H(p_1) = 1.0$.

Criterio di Split: Information Gain

Ad ogni bivio, l'albero calcola il Guadagno di Informazione (riduzione dell'entropia pesata) per ciascuna feature disponibile e sceglie quella che massimizza la purezza dei nodi figli:

$$\text{Information Gain} = H(p_1^{\text{padre}}) - \left( \frac{m_{\text{sinistro}}}{m_{\text{padre}}} H(p_1^{\text{sinistro}}) + \frac{m_{\text{destro}}}{m_{\text{padre}}} H(p_1^{\text{destro}}) \right)$$


Metodi di Insieme: Random Forests e XGBoost

Un singolo albero decisionale soffre tipicamente di alta varianza (overfitting). Per ottenere modelli ad altissime prestazioni e stabilità, utilizziamo i metodi di ensemble.

Random Forest (Bagging)

Costruisce centinaia di alberi decisionali profondi in parallelo. Ciascun albero viene addestrato su un campione di dati estratto con reinserimento (Bootstrap) e ad ogni split seleziona solo un sottoinsieme casuale di feature (Feature Bagging). La predizione finale è la votazione di maggioranza (o media) dell'insieme.

XGBoost (Gradient Boosting)

XGBoost costruisce alberi sequenziali poco profondi. Ciascun albero $t$ apprende a minimizzare una funzione obiettivo regolarizzata calcolata sui gradienti di errore del modello aggregato fino a quel punto:

$$\mathcal{L}^{(t)} = \sum_{i=1}^m \left[ g_i f_t(\mathbf{x}_i) + \frac{1}{2} h_i f_t^2(\mathbf{x}i) \right] + \gamma T + \frac{1}{2}\lambda \sum{j=1}^T w_j^2$$

Dove $g_i$ e $h_i$ sono le derivate prime e seconde (gradiente e hessiano) della funzione di perdita per il campione $i$.


Esempio Pratico Completo con Scikit-Learn e XGBoost

import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, f1_score
from sklearn.ensemble import RandomForestClassifier
from xgboost import XGBClassifier

# 1. Creazione dataset sbilanciato (95% negativi, 5% positivi)
X, y = make_classification(
    n_samples=2000, n_features=20, n_informative=12,
    weights=[0.95, 0.05], random_state=42
)

# 2. Split rigoroso Train (60%), CV (20%), Test (20%)
X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.40, random_state=42, stratify=y)
X_cv, X_test, y_cv, y_test = train_test_split(X_temp, y_temp, test_size=0.50, random_state=42, stratify=y_temp)

# 3. Addestramento Random Forest
rf = RandomForestClassifier(n_estimators=100, max_depth=8, random_state=42)
rf.fit(X_train, y_train)
y_pred_rf = rf.predict(X_test)

# 4. Addestramento XGBoost
xgb = XGBClassifier(
    n_estimators=150, max_depth=4, learning_rate=0.05,
    scale_pos_weight=19, # Bilanciamento del peso per la classe rara
    eval_metric="logloss", random_state=42
)
xgb.fit(X_train, y_train, eval_set=[(X_cv, y_cv)], verbose=False)
y_pred_xgb = xgb.predict(X_test)

# 5. Valutazione F1-Score sulla classe rara
f1_rf = f1_score(y_test, y_pred_rf)
f1_xgb = f1_score(y_test, y_pred_xgb)

print("=== REPORT COMPARATIVO SU DATASET SBILANCIATO ===")
print(f"Random Forest F1-Score: {f1_rf:.4f}")
print(f"XGBoost F1-Score:       {f1_xgb:.4f}\n")
print("Report dettagliato XGBoost:")
print(classification_report(y_test, y_pred_xgb, target_names=["Classe 0 (Nominale)", "Classe 1 (Anomalia)"]))

Conclusioni

Dominare la diagnostica dei modelli e le metriche avanzate permette di identificare con certezza i colli di bottiglia nei workflow di machine learning.

Nel prossimo articolo esploreremo la più rivoluzionaria architettura del decennio: i Transformer e i meccanismi di Self-Attention che alimentano i moderni Large Language Models.

FAQ

Perché è necessario suddividere i dati in tre insiemi (Train, CV, Test) anziché solo due?

Il Training set serve ad addestrare i pesi w e b; il Cross-Validation set serve a confrontare e scegliere i migliori iperparametri (es. grado polinomiale, lambda); il Test set viene tenuto rigorosamente isolato per valutare la reale capacità di generalizzazione finale senza contaminazioni o bias di selezione.

Cosa indica un errore di Training elevato e un errore di Validation altrettanto elevato?

Indica un problema di Alto Bias (Underfitting): il modello è troppo semplice o rigido per catturare la complessità dei dati. In questo scenario, raccogliere più dati di addestramento è inutile; occorre aumentare la complessità del modello, aggiungere nuove feature o diminuire il parametro di regolarizzazione lambda.

Cosa fare se il modello ha un errore di Training bassissimo ma un errore di Validation molto alto?

Indica un problema di Alta Varianza (Overfitting): il modello ha memorizzato il rumore del set di addestramento. Le soluzioni efficaci sono: raccogliere più dati di addestramento, ridurre il numero di feature non rilevanti o aumentare la penalizzazione di regolarizzazione lambda.

Cos'è l'Entropia di Shannon in un albero decisionale?

L'Entropia di Shannon H(p_1) = -p_1 * log2(p_1) - (1-p_1) * log2(1-p_1) misura il grado di disordine o impurità di un nodo rispetto alla distribuzione delle classi. Vale 0 per nodi purissimi (100% classe 1 o 0) e tocca il massimo 1.0 quando la distribuzione è equamente divisa al 50%.

Qual è la differenza fondamentale tra Random Forest e XGBoost?

Random Forest usa il Bagging: costruisce centinaia di alberi profondi in parallelo su campioni bootstrap indipendenti e ne fa la media per ridurre la varianza. XGBoost usa il Boosting: costruisce alberi sequenziali poco profondi in cui ciascun nuovo albero impara specificamente a correggere gli errori residui commessi dagli alberi precedenti.

Fonti