Top 25 Domande di Colloquio per Data Scientist nel 2026

Le 25 domande più frequenti nei colloqui per data scientist nel 2026, con risposte dettagliate, esempi di codice Python e strategie per affrontare ogni argomento con sicurezza.

Domande di colloquio per data scientist 2026

Il mercato dei data scientist rimane competitivo nel 2026, con selezioni che spaziano dalla statistica inferenziale all'architettura di sistemi di machine learning in produzione. Le aziende non cercano soltanto chi conosce la sintassi di scikit-learn: valutano la capacità di ragionare in modo rigoroso sui dati, di costruire pipeline robuste e di comunicare i risultati a interlocutori non tecnici. Questa guida raccoglie le 25 domande più frequenti nei colloqui per data scientist, con spiegazioni approfondite ed esempi di codice pronti all'uso.

Nei colloqui per data scientist i recruiter valutano tre livelli distinti: la solidità teorica (statistica, probabilità, teoria degli algoritmi), la competenza pratica (scrittura di codice pulito, gestione di dati reali, debug di modelli) e la capacità di tradurre i risultati in valore di business. Prepararsi su un solo livello non è sufficiente.

Fondamenti di Probabilità e Statistica (D1-D3)

D1. Qual è la differenza tra un test A/B frequentista e un approccio bayesiano?

L'approccio frequentista interpreta la probabilità come frequenza limite a lungo termine. Si fissa un livello di significatività alpha (tipicamente 0.05), si raccolgono i dati e si calcola il p-value: se questo è inferiore ad alpha si rifiuta l'ipotesi nulla. Il metodo è deterministico e non richiede conoscenze a priori, ma non permette di aggiornare le conclusioni man mano che arrivano nuovi dati.

L'approccio bayesiano incorpora la conoscenza a priori attraverso una distribuzione prior e la aggiorna con i dati osservati per ottenere la distribuzione posterior. Invece di un p-value, si ottiene un intervallo di credibilità che ha un'interpretazione probabilistica diretta: "la probabilità che il parametro si trovi in questo intervallo è del 95%".

In pratica, molte piattaforme di A/B testing online adottano approcci bayesiani perché consentono di prendere decisioni in modo sequenziale, senza dover definire in anticipo la dimensione del campione.

python
# binomial_test.py
from scipy import stats

# Two-sided binomial test: is the coin fair?
result = stats.binomtest(k=8, n=10, p=0.5, alternative='two-sided')
print(f"p-value: {result.pvalue:.4f}")  # 0.1094 (two-sided)
print(f"Reject H0 at alpha=0.05? {result.pvalue < 0.05}")  # False
python
# bayesian_vs_frequentist.py
import numpy as np
from scipy import stats

# Frequentist: confidence interval for a mean
data = np.array([23.1, 25.4, 22.8, 24.9, 23.7, 25.1, 24.3])
ci = stats.t.interval(0.95, df=len(data)-1, loc=np.mean(data), scale=stats.sem(data))
print(f"95% CI (frequentist): [{ci[0]:.2f}, {ci[1]:.2f}]")

# Bayesian: posterior with conjugate prior (Normal-Normal)
prior_mean, prior_var = 24.0, 4.0  # prior belief
data_mean, data_var = np.mean(data), np.var(data, ddof=1) / len(data)
# Posterior parameters (conjugate update)
post_var = 1 / (1/prior_var + 1/data_var)
post_mean = post_var * (prior_mean/prior_var + data_mean/data_var)
post_ci = stats.norm.interval(0.95, loc=post_mean, scale=np.sqrt(post_var))
print(f"95% credible interval (Bayesian): [{post_ci[0]:.2f}, {post_ci[1]:.2f}]")

D2. Come si interpreta correttamente un p-value?

Il p-value è la probabilità di osservare un risultato uguale o più estremo di quello ottenuto, assumendo che l'ipotesi nulla sia vera. Non è la probabilità che l'ipotesi nulla sia vera, né la probabilità che i risultati siano dovuti al caso. Un p-value basso indica che i dati sono improbabili sotto H0, ma non quantifica l'entità dell'effetto. Per questo motivo, il p-value va sempre accompagnato dalla dimensione dell'effetto (Cohen's d, odds ratio, ecc.) e dagli intervalli di confidenza.

D3. Cos'è la maldizione della dimensionalità e perché è rilevante per il machine learning?

All'aumentare del numero di dimensioni, lo spazio cresce esponenzialmente e i punti dati diventano progressivamente più sparsi. Questo fenomeno ha conseguenze dirette: le distanze euclidee perdono significatività (tutti i punti tendono ad avere distanze simili), i modelli basati sulla prossimità come KNN diventano inaffidabili, e la quantità di dati necessaria per coprire lo spazio in modo rappresentativo cresce in modo non gestibile. Le strategie per mitigare il problema includono la selezione delle feature, la riduzione dimensionale (PCA, UMAP) e la regolarizzazione.

Feature Engineering e Preparazione dei Dati (D4-D5)

D4. Come si gestiscono i dati mancanti in un dataset reale?

La scelta della strategia dipende dal meccanismo che genera i dati mancanti. Si distinguono tre casi: MCAR (Missing Completely At Random), in cui la mancanza è indipendente da tutti i valori; MAR (Missing At Random), in cui dipende da variabili osservate ma non dal valore mancante stesso; MNAR (Missing Not At Random), il caso più problematico, in cui il fatto stesso che il dato manchi dipende dal suo valore.

Le tecniche di imputazione avanzate come KNN imputation e MICE (Multiple Imputation by Chained Equations) preservano la struttura locale dei dati meglio della semplice media. Per dati MNAR, aggiungere una variabile indicatore che segnala la mancanza può conservare informazione predittiva.

python
# missing_data_strategies.py
import pandas as pd
from sklearn.impute import KNNImputer, SimpleImputer
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer

df = pd.DataFrame({
    'age': [25, 30, None, 45, None, 38],
    'income': [50000, None, 70000, 90000, 60000, None],
    'score': [85, 90, 78, None, 88, 92]
})

# Strategy 1: KNN imputation (preserves local structure)
knn_imp = KNNImputer(n_neighbors=2)
df_knn = pd.DataFrame(knn_imp.fit_transform(df), columns=df.columns)

# Strategy 2: Iterative imputation (MICE-like, models each feature)
iter_imp = IterativeImputer(max_iter=10, random_state=42)
df_iter = pd.DataFrame(iter_imp.fit_transform(df), columns=df.columns)

# Strategy 3: Add missingness indicator (preserves signal in the pattern)
df['income_missing'] = df['income'].isna().astype(int)
print(df_knn.round(1))

D5. Cos'è il target encoding e come si previene il data leakage?

Il target encoding sostituisce una variabile categorica con la media (o un'altra statistica) della variabile target calcolata sulle osservazioni dello stesso gruppo. Il rischio principale è il data leakage: se la media viene calcolata sull'intero dataset prima della cross-validation, il modello apprende informazioni sui dati di test durante l'addestramento. La soluzione corretta prevede l'uso della K-fold regularization: la codifica di ogni fold viene calcolata esclusivamente sugli altri fold.

python
# target_encoding.py
import pandas as pd
import numpy as np
from sklearn.model_selection import KFold

def target_encode_kfold(df, col, target, n_splits=5):
    """Target encoding with K-fold regularization to prevent leakage."""
    encoded = pd.Series(index=df.index, dtype=float)
    global_mean = df[target].mean()
    kf = KFold(n_splits=n_splits, shuffle=True, random_state=42)

    for train_idx, val_idx in kf.split(df):
        # Compute means only from training fold
        means = df.iloc[train_idx].groupby(col)[target].mean()
        encoded.iloc[val_idx] = df.iloc[val_idx][col].map(means)

    # Fill categories unseen in training fold with global mean
    encoded.fillna(global_mean, inplace=True)
    return encoded

df = pd.DataFrame({
    'city': ['Paris', 'Lyon', 'Paris', 'Marseille', 'Lyon', 'Paris',
             'Marseille', 'Lyon', 'Paris', 'Marseille'],
    'hired': [1, 0, 1, 0, 1, 1, 0, 0, 1, 1]
})
df['city_encoded'] = target_encode_kfold(df, 'city', 'hired')
print(df[['city', 'city_encoded', 'hired']])

Pronto a superare i tuoi colloqui su Data Science & ML?

Pratica con i nostri simulatori interattivi, flashcards e test tecnici.

Concetti Fondamentali di Machine Learning (D6-D9)

D6. Spiega il bias-variance tradeoff con un esempio pratico.

Il bias misura quanto le previsioni del modello si discostano sistematicamente dai valori reali: un modello con alto bias è troppo semplice e non cattura la struttura dei dati (underfitting). La varianza misura quanto le previsioni cambiano al variare del dataset di addestramento: un modello con alta varianza si adatta troppo ai dati di training e generalizza male (overfitting).

Esempio pratico: un albero decisionale profondo ha basso bias (interpola perfettamente i dati di training) ma alta varianza (ogni piccola perturbazione del dataset produce un albero completamente diverso). Un albero con profondità massima 2 ha alto bias ma bassa varianza. Il Random Forest riduce la varianza facendo la media di molti alberi profondi, mantenendo basso il bias.

La regolarizzazione (L1/L2, dropout nelle reti neurali, pruning negli alberi) è lo strumento principale per spostarsi lungo il tradeoff verso soluzioni con varianza più bassa.

D7. Quando si usa la regressione logistica e quando un gradient boosting?

La regressione logistica è preferibile quando l'interpretabilità dei coefficienti è necessaria (ad esempio in ambito medico o legale), quando i dati sono limitati e si vuole evitare l'overfitting, o quando le feature hanno già una relazione approssimativamente lineare con il log-odds dell'outcome. È anche preferibile in produzione quando la latenza è critica.

Il gradient boosting (XGBoost, LightGBM, CatBoost) eccelle quando esistono interazioni non lineari complesse tra feature, quando la dimensione del dataset lo giustifica (tipicamente oltre 10.000 osservazioni), e quando la performance predittiva è la priorità assoluta. Il prezzo da pagare è una maggiore complessità computazionale e interpretativa.

D8. Come funziona un Random Forest e perché riduce la varianza?

Il Random Forest costruisce un insieme di alberi decisionali addestrati ognuno su un bootstrap sample del dataset originale (bagging). Inoltre, in ogni split considera solo un sottoinsieme casuale delle feature (tipicamente la radice quadrata del numero totale di feature per la classificazione). La previsione finale è la media (regressione) o la moda (classificazione) delle previsioni dei singoli alberi.

La riduzione della varianza deriva dalla decorrelazione degli alberi: poiché ogni albero vede un sottoinsieme diverso di dati e di feature, gli errori tendono ad essere indipendenti tra loro. La media di tante variabili casuali indipendenti ha una varianza inversamente proporzionale al loro numero, da qui il miglioramento.

D9. Cos'è la regolarizzazione L1 vs L2 e quando scegliere l'una o l'altra?

La regolarizzazione L2 (Ridge) aggiunge alla funzione di loss il termine lambda * somma(w_i^2). Penalizza i pesi grandi ma non li porta esattamente a zero, producendo soluzioni stabili quando le feature sono correlate tra loro.

La regolarizzazione L1 (Lasso) aggiunge lambda * somma(|w_i|). Per la geometria della norma L1, ha la tendenza a portare i pesi di feature irrilevanti esattamente a zero, producendo soluzioni sparse. È preferibile quando si sospetta che solo un sottoinsieme delle feature sia informativo e si vuole automaticamente selezionarle.

L'Elastic Net combina entrambe le penalizzazioni ed è utile quando ci sono gruppi di feature correlate di cui si vuole preservare almeno un rappresentante.

Valutazione dei Modelli e Validazione (D10-D11)

D10. Come si valuta un modello su dati fortemente sbilanciati?

L'accuracy è una metrica ingannevole su dati sbilanciati: un classificatore che predice sempre la classe maggioritaria raggiunge il 95% di accuracy su un dataset 95/5, pur non avendo alcuna utilità. Le metriche appropriate dipendono dal costo relativo degli errori:

  • Precision e Recall: precision = TP/(TP+FP), recall = TP/(TP+FN). Usare F1-score come media armonica quando i falsi positivi e i falsi negativi hanno peso simile.
  • AUPRC (Area Under Precision-Recall Curve): più informativa di ROC AUC quando la classe positiva è rara, perché non è influenzata dai veri negativi.
  • ROC AUC: misura la capacità discriminativa complessiva del modello, ma può essere ottimistica su dataset sbilanciati.
python
# imbalanced_metrics.py
from sklearn.metrics import (
    classification_report, precision_recall_curve,
    average_precision_score, roc_auc_score
)
import numpy as np

# Simulated predictions on imbalanced data
np.random.seed(42)
y_true = np.array([0]*950 + [1]*50)  # 95/5 imbalance
y_scores = np.random.beta(2, 5, 1000)  # predicted probabilities
y_scores[y_true == 1] += 0.3  # positive class scores slightly higher
y_scores = np.clip(y_scores, 0, 1)
y_pred = (y_scores > 0.5).astype(int)

print(classification_report(y_true, y_pred, digits=3))
print(f"ROC AUC: {roc_auc_score(y_true, y_scores):.3f}")
print(f"Average Precision (AUPRC): {average_precision_score(y_true, y_scores):.3f}")

D11. Come si previene il data leakage durante la cross-validation?

Il data leakage si verifica quando informazioni provenienti dal fold di test influenzano il preprocessing o l'addestramento del modello, producendo stime di performance ottimisticamente distorte. L'errore più comune è applicare lo scaling o l'imputazione sull'intero dataset prima della cross-validation: in questo modo, le statistiche (media, deviazione standard) vengono calcolate includendo i dati di test, che diventano de facto "visibili" al modello.

La soluzione corretta è incapsulare tutti i passi di preprocessing in una Pipeline di scikit-learn. La pipeline garantisce che ogni trasformazione venga fittata esclusivamente sui dati di training di ogni fold.

python
# leakage_prevention.py
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import cross_val_score
import numpy as np

X = np.random.randn(1000, 10)
y = (X[:, 0] + X[:, 1] > 0).astype(int)

# WRONG: fit scaler on all data, then cross-validate
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)  # leakage: test fold info in scaling

# CORRECT: pipeline ensures preprocessing fits only on training folds
pipeline = Pipeline([
    ('imputer', SimpleImputer(strategy='median')),
    ('scaler', StandardScaler()),
    ('model', GradientBoostingClassifier(n_estimators=100, random_state=42))
])
scores = cross_val_score(pipeline, X, y, cv=5, scoring='roc_auc')
print(f"AUC (no leakage): {scores.mean():.3f} +/- {scores.std():.3f}")

Il leakage è una delle cause più comuni di modelli che performano bene in sviluppo e falliscono in produzione. Verificare sempre che tutte le trasformazioni (scaling, encoding, imputazione, selezione delle feature) vengano fittate esclusivamente sui dati di training, mai sul dataset completo.

Deep Learning e Reti Neurali (D12-D14)

D12. Spiega il meccanismo di self-attention nei Transformer.

L'attenzione trasforma ogni elemento di una sequenza in una combinazione pesata di tutti gli altri elementi. Per ogni token di input, vengono calcolati tre vettori: Query (Q), Key (K) e Value (V) tramite proiezioni lineari apprese. Il punteggio di attenzione tra due token è il prodotto scalare tra la loro Query e Key, diviso per la radice quadrata della dimensione (per stabilizzare i gradienti). Dopo un softmax, questi punteggi diventano pesi che determinano quanto ogni token "presta attenzione" agli altri.

Il meccanismo multi-head esegue questa operazione in parallelo su sottospazi diversi, permettendo al modello di catturare simultaneamente relazioni di tipo diverso (sintattico, semantico, coreference) nella stessa sequenza.

python
# self_attention.py
import torch
import torch.nn.functional as F

def self_attention(x, d_k):
    """Scaled dot-product self-attention from scratch."""
    # x shape: (batch_size, seq_len, d_model)
    batch_size, seq_len, d_model = x.shape

    # Linear projections for Q, K, V
    W_q = torch.randn(d_model, d_k) * 0.1
    W_k = torch.randn(d_model, d_k) * 0.1
    W_v = torch.randn(d_model, d_k) * 0.1

    Q = x @ W_q  # (batch, seq_len, d_k)
    K = x @ W_k
    V = x @ W_v

    # Scaled dot-product attention
    scores = Q @ K.transpose(-2, -1) / (d_k ** 0.5)  # (batch, seq_len, seq_len)
    weights = F.softmax(scores, dim=-1)  # attention weights
    output = weights @ V  # (batch, seq_len, d_k)

    return output, weights

# Example: 1 batch, 4 tokens, 8-dim embeddings
x = torch.randn(1, 4, 8)
out, attn = self_attention(x, d_k=8)
print(f"Output shape: {out.shape}")    # (1, 4, 8)
print(f"Attention weights:\n{attn[0].detach().numpy().round(3)}")

D13. Cosa sono il vanishing gradient e l'exploding gradient e come si affrontano?

Durante la backpropagation, i gradienti vengono moltiplicati ripetutamente per i pesi dello strato precedente. Se questi pesi hanno modulo sistematicamente inferiore a 1, i gradienti tendono a zero negli strati più profondi (vanishing gradient), rendendo impossibile l'aggiornamento dei pesi iniziali. Se i pesi hanno modulo superiore a 1, i gradienti crescono esponenzialmente (exploding gradient), causando instabilità numerica.

Soluzioni per il vanishing gradient: funzioni di attivazione che non saturano (ReLU e varianti), batch normalization, connessioni residuali (ResNet), architetture LSTM/GRU per le sequenze.

Soluzioni per l'exploding gradient: gradient clipping (si limita la norma del gradiente a un valore massimo), inizializzazione attenta dei pesi (Xavier, He), batch normalization.

D14. Quando usare il transfer learning e come si implementa il fine-tuning?

Il transfer learning è conveniente quando il dataset disponibile è insufficiente per addestrare un modello da zero, ma il problema target è sufficientemente simile al dominio su cui è stato pre-addestrato il modello base. In computer vision si usano reti pre-addestrate su ImageNet (ResNet, EfficientNet, ViT); in NLP si parte da modelli pre-addestrati come BERT, RoBERTa o modelli di linguaggio più recenti.

Il fine-tuning classico prevede due fasi: prima si addestrano solo gli strati aggiunti (testa classificatrice) con il backbone congelato, poi si sblocca progressivamente il backbone e si riaddestra con un learning rate molto basso (tipicamente 1/10 di quello usato per la testa). Questo approccio evita di distruggere le rappresentazioni pre-apprese nelle prime epoche.

SQL e Manipolazione dei Dati (D15-D16)

D15. Come si estrae il secondo salario più alto per dipartimento con SQL?

Questo problema ricorre spesso nei colloqui perché richiede di ragionare con subquery o window functions. L'approccio con subquery correlata è portabile su tutti i principali database:

sql
-- second_highest_salary.sql
-- Approach: correlated subquery counting distinct higher salaries
SELECT d.department_name, e.employee_name, e.salary
FROM employees e
JOIN departments d ON e.department_id = d.id
WHERE (
    SELECT COUNT(DISTINCT e2.salary)
    FROM employees e2
    WHERE e2.department_id = e.department_id
      AND e2.salary > e.salary
) = 1
ORDER BY d.department_name;

L'alternativa più elegante su database che supportano le window functions è usare DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) e filtrare per rank = 2.

D16. Qual è la differenza tra JOIN, LEFT JOIN e FULL OUTER JOIN?

INNER JOIN restituisce solo le righe per cui esiste una corrispondenza in entrambe le tabelle. LEFT JOIN restituisce tutte le righe della tabella sinistra, con NULL per le colonne della tabella destra quando non esiste corrispondenza: è utile per trovare entità prive di record associati (es. clienti senza ordini). FULL OUTER JOIN restituisce tutte le righe di entrambe le tabelle, con NULL dove manca la corrispondenza: è utile per confrontare due dataset e identificare le discrepanze in entrambe le direzioni.

Nei colloqui, una domanda tipica di follow-up è: "Come troveresti i clienti che non hanno mai effettuato un ordine?" La risposta corretta usa un LEFT JOIN con un filtro WHERE orders.id IS NULL.

Data Science Applicata e System Design (D17-D20)

D17. Come si struttura un sistema di raccomandazione scalabile?

I sistemi di raccomandazione si dividono in tre categorie principali. Il collaborative filtering si basa sulla similarità tra utenti o tra item (user-based o item-based), o in forma più moderna sulla fattorizzazione di matrici (ALS, SVD) che apprende embedding latenti per utenti e item. Il content-based filtering usa le caratteristiche degli item (genere, categoria, testo) per raccomandare item simili a quelli già apprezzati dall'utente. I sistemi ibridi combinano entrambi gli approcci.

In produzione, la scalabilità richiede una separazione tra candidate generation (recuperare rapidamente un sottoinsieme di centinaia di candidati usando tecniche di Approximate Nearest Neighbor) e ranking (riordinare i candidati con un modello più complesso). Piattaforme come YouTube e Spotify adottano questa architettura a due stadi.

D18. Come si gestisce il cold start problem?

Il cold start problem si manifesta in due varianti: nuovo utente (nessuna storia di interazioni) e nuovo item (nessuna valutazione ricevuta). Per i nuovi utenti, le strategie includono l'onboarding esplicito (chiedere le preferenze), l'uso di dati demografici per raccomandare item popolari nel segmento, e il fallback a raccomandazioni basate sulla popolarità globale. Per i nuovi item, si sfrutta il content-based filtering per trovare item simili a quelli già noti, o si usano tecniche di exploration come l'epsilon-greedy o gli algoritmi banditi per raccogliere dati rapidamente.

D19. Come si monitora un modello in produzione e come si rileva il model drift?

Il monitoring di un modello ML in produzione richiede il tracciamento di tre tipi di drift. Il data drift (o covariate shift) si verifica quando la distribuzione degli input cambia: si rileva confrontando le statistiche descrittive e le distribuzioni delle feature in produzione con quelle del training set, usando test statistici come il Kolmogorov-Smirnov o il Population Stability Index (PSI). Il concept drift si verifica quando cambia la relazione tra input e output (ad esempio, il comportamento degli utenti cambia stagionalmente). Il prediction drift monitora la distribuzione delle previsioni del modello nel tempo.

Il sistema ideale prevede alert automatici quando il PSI di una feature supera una soglia critica, con pipeline di re-training attivate automaticamente o su approvazione umana.

D20. Qual è la dimensione del campione necessaria per un test A/B affidabile?

La dimensione del campione dipende da quattro parametri: il livello di significatività (alpha, tipicamente 0.05), la potenza statistica (1-beta, tipicamente 0.8 o 0.9), la dimensione dell'effetto minimo rilevante (Minimum Detectable Effect, MDE) e la varianza della metrica. La relazione fondamentale è: quanto più piccolo è l'effetto da rilevare, tanto più grande deve essere il campione.

Per esperimenti su metriche di conversione, un MDE del 5% richiede tipicamente campioni dell'ordine delle decine di migliaia per variante. Ridurre l'MDE al 2% quadruplica approssimativamente la dimensione del campione necessaria. È importante decidere l'MDE prima di avviare l'esperimento, non dopo aver visto i dati preliminari.

Pronto a superare i tuoi colloqui su Data Science & ML?

Pratica con i nostri simulatori interattivi, flashcards e test tecnici.

Python e Pandas (D21-D22)

D21. Qual è la differenza tra map, apply e transform in pandas?

Questi tre metodi operano su oggetti diversi e a livelli diversi di astrazione. map opera su una Series e applica una funzione o un dizionario elemento per elemento: è il metodo più veloce per trasformazioni semplici. apply opera su una Series o su un DataFrame e permette di applicare funzioni arbitrarie lungo un asse: può restituire scalari, Series o DataFrame. transform è pensato per operazioni di group-by che restituiscono un oggetto della stessa dimensione dell'input, permettendo di fare broadcast dei risultati aggregati sul DataFrame originale.

python
# pandas_operations.py
import pandas as pd

df = pd.DataFrame({
    'team': ['A', 'A', 'B', 'B', 'A'],
    'score': [10, 20, 30, 40, 50]
})

# map: element-wise on Series
df['team_upper'] = df['team'].map({'A': 'Alpha', 'B': 'Beta'})

# apply: arbitrary function per row
df['score_label'] = df['score'].apply(lambda x: 'high' if x > 25 else 'low')

# transform: group-level, same shape output (broadcasts back)
df['team_mean'] = df.groupby('team')['score'].transform('mean')
df['score_normalized'] = df.groupby('team')['score'].transform(
    lambda x: (x - x.mean()) / x.std()
)
print(df)

D22. Come si interpreta e si usa SHAP per spiegare le previsioni di un modello?

SHAP (SHapley Additive exPlanations) si basa sulla teoria dei giochi cooperativi per attribuire a ciascuna feature il contributo marginale alle previsioni del modello. Il valore SHAP di una feature per una singola osservazione rappresenta quanto quella feature sposta la previsione rispetto al valore base (la media delle previsioni su tutto il dataset).

SHAP è model-agnostic ma ha implementazioni ottimizzate per alberi (TreeSHAP, con complessità polinomiale invece che esponenziale). I grafici summary plot mostrano l'importanza globale delle feature e la direzione dell'effetto; i waterfall plot mostrano la scomposizione della previsione per una singola osservazione.

python
# feature_importance_shap.py
import shap
import xgboost as xgb
from sklearn.datasets import make_classification

# Generate synthetic dataset
X, y = make_classification(n_samples=1000, n_features=10,
                           n_informative=5, random_state=42)

# Train XGBoost model
model = xgb.XGBClassifier(n_estimators=100, random_state=42, eval_metric='logloss')
model.fit(X, y)

# SHAP explanation
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X)

# Global importance: mean absolute SHAP value per feature
import numpy as np
importance = np.abs(shap_values).mean(axis=0)
for i in np.argsort(importance)[::-1]:
    print(f"Feature {i}: {importance[i]:.4f}")

Riduzione Dimensionale e Apprendimento Non Supervisionato (D23-D24)

D23. Confronta PCA, t-SNE e UMAP per la visualizzazione e il preprocessing.

I tre metodi hanno obiettivi e proprietà profondamente diversi:

| Metodo | Lineare | Preserva struttura globale | Velocità (100K punti) | Caso d'uso | |--------|---------|---------------------------|------------------------|------------| | PCA | Sì | Sì | Secondi | Preprocessing, riduzione feature | | t-SNE | No | No | Minuti | Visualizzazione cluster (dati piccoli) | | UMAP | No | Parzialmente | Secondi | Visualizzazione + preprocessing |

PCA massimizza la varianza spiegata proiettando i dati sulle direzioni di maggiore variabilità: è interpretabile (le componenti principali sono combinazioni lineari delle feature originali) e veloce, ma non cattura strutture non lineari. t-SNE minimizza la divergenza KL tra le distribuzioni di similarità nello spazio originale e in quello ridotto: eccelle nel rivelare cluster, ma non preserva le distanze globali e non è deterministico. UMAP è generalmente più veloce di t-SNE, meglio scalabile e può essere usato anche per preprocessing (a differenza di t-SNE che non supporta la trasformazione di nuovi punti).

D24. Cos'è l'algoritmo DBSCAN e quando è preferibile a K-Means?

DBSCAN (Density-Based Spatial Clustering of Applications with Noise) individua cluster come regioni ad alta densità separate da regioni a bassa densità. I due iperparametri principali sono epsilon (il raggio del vicinato) e minPts (il numero minimo di punti nel vicinato per considerare un punto come core point). I punti che non appartengono ad alcun cluster vengono etichettati come outlier.

DBSCAN è preferibile a K-Means in tre situazioni: quando i cluster hanno forma arbitraria (non sferica), quando il numero di cluster non è noto a priori, e quando si vuole rilevare automaticamente gli outlier. K-Means assume cluster sferici di dimensione simile e richiede di specificare K in anticipo; tuttavia è più veloce e interpretabile quando queste assunzioni sono soddisfatte.

Comunicazione e Impatto sul Business (D25)

D25. Come si presenta un'analisi tecnica a un pubblico non tecnico?

La comunicazione dei risultati è una competenza spesso sottovalutata nel percorso formativo dei data scientist, ma determinante per l'impatto reale del lavoro. I principi fondamentali sono:

Tradurre in metriche di business: invece di "il modello raggiunge un F1-score di 0.82", comunicare "il modello riduce del 23% i falsi positivi rispetto al processo attuale, risparmiando circa 40 ore di revisione manuale a settimana".

Usare visualizzazioni intuitive: i grafici di distribuzione e i confusion matrix sono familiari ai tecnici ma opachi per i manager. I grafici a barre con threshold chiari, le tabelle comparative prima/dopo e le simulazioni scenariche comunicano meglio con un pubblico misto.

Essere espliciti sull'incertezza: i modelli ML producono previsioni probabilistiche, non certezze. Comunicare sempre gli intervalli di confidenza o la precision attesa, e spiegare in quali condizioni il modello potrebbe essere meno affidabile.

Strutturare la narrazione: iniziare con la conclusione ("il modello proposto riduce i costi del 15%"), poi presentare l'evidenza, poi rispondere alle domande metodologiche. Il pubblico non tecnico non ha bisogno di seguire il percorso analitico dall'inizio alla fine.

Conclusione

Affrontare un colloquio da data scientist nel 2026 richiede una preparazione multidimensionale. I candidati che si distinguono sono quelli che:

  • Padroneggiano i fondamenti statistici senza fermarsi alla formula, ma sapendo quando un'assunzione è violata e quali sono le conseguenze
  • Scrivono codice Python leggibile e privo di leakage, usando pipeline e buone pratiche ingegneristiche
  • Conoscono SQL in modo fluido per interrogazioni analitiche complesse
  • Sanno spiegare le decisioni di modellazione in termini di tradeoff (bias/varianza, interpretabilità/performance, velocità/accuratezza)
  • Comunicano i risultati in termini di impatto sul business, non solo di metriche tecniche
  • Hanno familiarità con le architetture di sistema (sistemi di raccomandazione, monitoring in produzione, design di esperimenti)

La preparazione più efficace combina la revisione teorica con la pratica su progetti reali e la simulazione di colloqui in condizioni autentiche.

Inizia a praticare!

Metti alla prova le tue conoscenze con i nostri simulatori di colloquio e test tecnici.

Tag

#data-science
#interview
#machine-learning
#python
#statistics

Condividi

Articoli correlati