Machine Learning per classificazione: quando usare quale modello

Durante il mio master in Ingegneria Elettronica, ho sviluppato modelli ML per il rilevamento di persone da segnali radar UWB. Questa esperienza mi ha insegnato che il modello “migliore” non esiste in assoluto: dipende dai dati, dal contesto e dai vincoli applicativi.

Il problema di classificazione

Dado un set di features (input), predire una classe (output categorico):

Input Features:
├─ Età: 35 anni
├─ Reddito: 45.000€
├─ Score creditizio: 750
└─ Numero carte: 2

Modello ML

Output: Classe = "Approvato" / "Rifiutato"

Albero decisionale dei modelli

               Classificazione?

        ┌─────────────┼──────────────┐
        │             │              │
    Lineare       Non-lineare    Insieme
        │             │              │
        ├─Logistic  ├─SVM (RBF)  ├─Random Forest
        │ Regression │             │ ├─Gradient Boosting
        │          ├─Neural Net  │ ├─Voting
        │          │             │ └─Stacking
        │          └─KNN         │
        │                         │
    Semplice             Complesso  Robusto
    Fast                 Lento      Slow
    Interpretabile       Black Box  Gray Box

Modelli principali e use case

1. Logistic Regression

Quando usarla:

  • ✅ Dataset piccolo (<10k samples)
  • ✅ Necessaria interpretabilità
  • ✅ Baseline veloce

Quando evitarla:

  • ❌ Classi non lineari
  • ❌ Molte interazioni tra features
from sklearn.linear_model import LogisticRegression

# Predizione: Malattia cardiaca (0=No, 1=Yes)
# Features: [età, colesterolo, pressione, ...]

model = LogisticRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)

# Interpretabilità: coefficienti = importanza feature
coefficients = model.coef_[0]
# [+0.05, +0.12, -0.03, ...] → positivo=aumenta rischio

2. Support Vector Machine (SVM)

Quando usarla:

  • ✅ Feature space di alta dimensionalità
  • ✅ Buona generalizzazione
  • ✅ Binary classification complessa

Quando evitarla:

  • ❌ Dataset molto grande (>100k)
  • ❌ Necessari probability estimates accurati
from sklearn.svm import SVC

# Kernel RBF per classi non-lineari
model = SVC(kernel='rbf', gamma='scale')
model.fit(X_train, y_train)

# Decision boundary: hyperplane ad alta dimensionalità

3. Random Forest

Quando usarla:

  • ✅ Dataset misto (numerico + categorico)
  • ✅ Robustezza e low-variance
  • ✅ Feature importance built-in
  • ✅ Parallellizzabile

Quando evitarla:

  • ❌ Necessaria interpretabilità (black-box)
  • ❌ Dataset con molti outliers
from sklearn.ensemble import RandomForestClassifier

model = RandomForestClassifier(n_estimators=100, max_depth=10)
model.fit(X_train, y_train)

# Feature importance
importances = model.feature_importances_
# [0.25, 0.15, 0.12, ...] → percentuale importanza

4. Gradient Boosting (XGBoost, LightGBM)

Quando usarla:

  • ✅ Competition & Kaggle (vincitore 90% delle volte)
  • ✅ Accuratezza massima
  • ✅ Gestisce overfitting con early stopping
  • ✅ Feature importance non-lineare

Quando evitarla:

  • ❌ Bassa latenza richiesta
  • ❌ Dataset piccolissimo
  • ❌ Interpretabilità critica
import xgboost as xgb

model = xgb.XGBClassifier(
    n_estimators=100,
    learning_rate=0.1,
    max_depth=5,
    early_stopping_rounds=10
)
model.fit(X_train, y_train, eval_set=[(X_val, y_val)])

5. Reti Neurali

Quando usarla:

  • ✅ Dati non-strutturati (immagini, testo)
  • ✅ Pattern complessi gerarchici
  • ✅ Transfer learning disponibile
  • ✅ Grande quantità di dati (>100k)

Quando evitarla:

  • ❌ Dataset piccolo (<1k)
  • ❌ Computazione device (edge)
  • ❌ Interpretabilità importante
import tensorflow as tf

model = tf.keras.Sequential([
    tf.keras.layers.Dense(64, activation='relu', input_shape=(n_features,)),
    tf.keras.layers.Dropout(0.3),
    tf.keras.layers.Dense(32, activation='relu'),
    tf.keras.layers.Dense(1, activation='sigmoid')  # Binary classification
])

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=20, batch_size=32, validation_split=0.2)

Metriche di valutazione

Non usare solo accuracy! Dipende dal problema:

                    Predizione
                  Positivo | Negativo
Real   Positivo │   TP    |   FN
       Negativo │   FP    |   TN

Accuracy = (TP + TN) / Total       ← Generale
Precision = TP / (TP + FP)          ← Falsi positivi critici
Recall = TP / (TP + FN)             ← Falsi negativi critici
F1 = 2 * (Precision * Recall) / (Precision + Recall)  ← Balance

Esempi:

Spam detection → Precision alto (non infastidire utenti)

Diagnosi cancro → Recall alto (non perdere casi)

Loan approval → F1-score equilibrato

Workflow di ML in pratica

1. Data Collection
   └─ 1000 email (spam/non-spam)

2. Exploratory Data Analysis (EDA)
   ├─ Distribuzioni
   ├─ Outliers
   └─ Correlazioni

3. Feature Engineering
   ├─ Tokenizzazione
   ├─ TF-IDF
   └─ Normalizzazione

4. Train/Test Split
   ├─ 80% training
   ├─ 10% validation
   └─ 10% test

5. Model Selection & Training
   ├─ Logistic Regression (baseline)
   ├─ SVM
   ├─ Random Forest
   └─ XGBoost

6. Hyperparameter Tuning
   ├─ Grid Search
   ├─ Random Search
   └─ Bayesian Optimization

7. Cross-Validation
   └─ K-fold per robustezza

8. Final Evaluation
   └─ Test set (unseen data)

9. Deployment
   └─ Model serving (Flask, FastAPI, ONNX)

Racconto dalla ricerca: UWB Person Detection

Nel mio paper su MDPI (Febbraio 2022), abbiamo confrontato modelli ML per rilevare persone da radar UWB in condizioni NLOS (non-line-of-sight):

Dataset: 5000 samples da diverse posizioni
Features: Raw radar signals + engineered features

Risultati:
├─ Random Forest: 94% accuracy, 50ms inference ✓
├─ SVM (RBF): 96% accuracy, 200ms inference
├─ Neural Net: 97% accuracy, 500ms inference
└─ Logistic Reg: 78% accuracy, 5ms inference

Winner: Random Forest (miglior tradeoff)

La scelta del modello giusto è un’arte: bilanciare accuratezza, velocità, interpretabilità e costo computazionale.