Prendi un modello che in laboratorio azzeccava il 98% dei casi. Lo metti sui dati veri di lunedì mattina e arriva al 70%. La prima reazione è pensare a sfortuna, o a “dati sporchi”. Quasi sempre non è né una cosa né l’altra: il 98% era vero, era solo la misura sbagliata. Era stato calcolato, per intero o in parte, sugli stessi esempi con cui il modello aveva studiato. È il problema che la divisione dei dati in tre mucchi esiste per evitare, ed è anche il motivo per cui un numero di accuratezza senza la frase “misurato su quali dati” non vuole dire assolutamente niente. I tre mucchi hanno un nome e un mestiere ciascuno: train, dove il modello impara; validation, dove si sceglie; test, dove si misura una volta sola.
In questo articolo scoprirai:
- Il modello che va benissimo in prova e male sul serio
- Cosa succede davvero: tre mucchi con tre mestieri diversi
- Il conto: cento esempi, e cosa cambia se il test lo guardi venti volte
- Dove lo vedi all'opera: il dato che passa dalla parte sbagliata
- Il leakage per gruppo: quando lo stesso soggetto sta in due mucchi
- Cosa resta da sapere: quando i dati sono pochi, e quando dividere a caso è sbagliato
Il modello che va benissimo in prova e male sul serio
La documentazione di scikit-learn lo dice in una riga che vale più di un capitolo: «imparare i parametri di una funzione di predizione e testarla sugli stessi dati è un errore metodologico: un modello che si limitasse a ripetere le etichette degli esempi che ha appena visto avrebbe un punteggio perfetto ma non predirebbe nulla di utile» (scikit-learn, guida alla cross-validation, traduzione nostra). Non è una precauzione teorica: esiste un classificatore che ottiene il 100% di accuratezza sui dati di addestramento senza aver imparato niente, ed è il più banale di tutti, il “primo vicino”, che per ogni esempio cerca il punto più simile nell’archivio. Se il punto è nell’archivio, il più simile a sé stesso è sé stesso. Accuratezza 100%, sempre, per costruzione.
Questo è il caso limite, ma la stessa dinamica in scala ridotta è ciò che produce il salto 98% → 70%. Il fenomeno vicino, e più noto, è quando un modello impara troppo bene i casi che ha visto: lì si osserva il sintomo. Qui parliamo del metodo che permette di accorgersene, perché senza tre mucchi separati l’overfitting è invisibile, e un modello che ha memorizzato appare identico a un modello che ha capito.
Dal train al test: perché due mucchi non bastano
C’è una seconda ragione, più sottile e più frequente nei progetti reali. Anche tenendo da parte un pezzo di dati, se lo si guarda venti volte per decidere quale versione del modello portare in produzione, quel pezzo di dati smette di essere una misura pulita: diventa, di fatto, dati di addestramento passati attraverso le mani di chi sceglie. È questo il motivo per cui i mucchi sono tre e non due, ed è una delle ragioni concrete dietro i progetti AI che non arrivano mai in produzione.
Train, validation e test: tre mucchi con tre mestieri diversi
La divisione in train, validation e test assegna a tre porzioni disgiunte dello stesso dataset tre compiti che non si possono sovrapporre: sul train il modello aggiusta i propri parametri interni; sul validation chi lavora confronta configurazioni diverse, quanti strati, quale learning rate, quando fermarsi, e sceglie; sul test si calcola una sola volta, alla fine, la stima di come il modello andrà su dati che nessuno ha mai guardato. Ogni volta che una porzione viene usata per prendere una decisione, perde la capacità di misurare in modo imparziale quella stessa decisione: per questo il test si tocca una volta e poi si chiude.
Il verbo chiave è “decidere”. Il train serve a far avvenire l’addestramento, le correzioni automatiche dei pesi. Il validation serve alle decisioni umane, quelle che nessun algoritmo prende: architettura, iperparametri, quale delle tre idee tenere. Il test non serve a decidere niente, e proprio per questo è l’unico che può misurare.
Il validation e il test si consumano con l’uso
Google, nel suo corso ufficiale, aggiunge l’avvertimento che di solito viene ignorato: i set di validation e di test si «consumano» con l’uso ripetuto, più volte si usano gli stessi dati per prendere decisioni, minore è la fiducia che il modello funzionerà su dati nuovi, e la raccomandazione è raccogliere dati freschi per rinfrescarli (Machine Learning Crash Course). Lo stesso documento dice anche che non esistono percentuali obbligatorie: l’esempio mostra 70% / 15% / 15%, ma il vincolo vero è che il test contenga abbastanza esempi per dare un risultato statisticamente significativo. E prescrive una pulizia che quasi nessuno fa: cancellare dal validation e dal test gli esempi che sono duplicati di esempi del train.
Il conto: cento esempi, e cosa cambia se il test lo guardi venti volte
Mettiamo cento esempi etichettati, divisi 70 / 15 / 15 come nell’esempio di Google. Prima cosa da notare: su un test da 15 esempi, un solo esempio vale 6,7 punti percentuali (1/15 = 0,0667). Passare da 12 a 13 risposte giuste fa salire l’accuratezza da 80% a 86,7%, e questo non è un miglioramento del modello: è un esempio. La granularità della misura è il primo numero da guardare, sempre.
Secondo conto, quello che smonta il 98%. L’errore standard di un’accuratezza stimata su n esempi è √(p(1−p)/n). Con un modello che vale davvero 80% e n = 15: √(0,8 × 0,2 / 15) = 0,103, cioè 10,3 punti percentuali di errore standard, e un intervallo di confidenza al 95% che va da circa 60% a 100%. Per avere una precisione di ±2,5 punti serve n ≈ 1.000 esempi di test (errore standard 1,26 punti). Un “98%” misurato su 15 casi e un “98%” misurato su mille casi sono due frasi diverse scritte con le stesse cifre.
Perché scegliere il modello guardando il test gonfia il risultato
Terzo conto, ed è il più istruttivo. Supponiamo venti tentativi, venti configurazioni diverse, tutte in realtà equivalenti, con accuratezza vera 80%. Sul test da 15 esempi, la probabilità che un singolo tentativo mostri 14 o 15 risposte giuste (≥93%) è, per la distribuzione binomiale, P(14) + P(15) = 0,132 + 0,035 = 16,7%. Se i venti tentativi si trattano come indipendenti, la probabilità che almeno uno arrivi a quel risultato è 1 − (1 − 0,167)²⁰ = 97,4%.
Tradotto: prendendo venti modelli mediocri e scegliendo il migliore sul test, si è praticamente certi di trovarne uno che dichiara 93% mentre vale 80%. Non serve barare; basta guardare. È esattamente il rischio che scikit-learn descrive come «la conoscenza del test che filtra nel modello», e la ragione per cui il validation esiste: se le venti prove le fai sul validation, la selezione la paghi lì, e il test rimane un giudice esterno. Nell’esempio canonico della documentazione, 150 fiori iris, 90 in train e 60 in test, il punteggio sul test è 0,96, mentre una 5-fold cross-validation sull’intero dataset dà 0,98 con deviazione standard 0,02: due misure legittime, due numeri diversi, e la differenza è tutta nel metodo.
Dove lo vedi all’opera: il dato che passa dalla parte sbagliata
La divisione fatta bene protegge da qualcosa che ha un nome preciso: data leakage, l’informazione che filtra dal futuro o dal test verso l’addestramento. Non è un problema di dilettanti. Nella rassegna di Kapoor e Narayanan, 329 lavori scientifici in 17 campi diversi risultano affetti da errori di leakage, con una tassonomia di otto tipi distinti; nel loro caso di studio sulla previsione delle guerre civili, tutti i paper che dichiaravano la superiorità dei modelli complessi non si riproducono, e una volta corretto il leakage i modelli sofisticati non battono la regressione logistica di decenni prima (Leakage and the Reproducibility Crisis in ML-based Science).
Le forme di data leakage che riconosci in azienda
La colonna che contiene la risposta di straforo. Prevedi l’abbandono del cliente e nel dataset c’è il campo “data di disdetta”, o “motivo chiusura”, o un flag compilato dall’operatore dopo il fatto. Il modello impara a leggere il risultato invece di prevederlo: accuratezza spettacolare in prova, inutile in produzione, dove quella colonna al momento della predizione è vuota. Il tutorial di Kaggle chiama questa forma target leakage e la distingue dalla train-test contamination, dove è la preparazione dei dati a mescolare i due lati (Data Leakage, Kaggle Learn). Il test controllo è una domanda sola: questo dato esisteva già, nel momento in cui avrei dovuto decidere?
Il tempo mescolato a caso. Su dati con un ordine, vendite, consumi, traffico, prezzi, una divisione casuale mette il mercoledì nel train e il martedì nel test, e il modello prevede il passato conoscendo il futuro. scikit-learn è esplicito: le tecniche classiche assumono esempi indipendenti e identicamente distribuiti e «produrrebbero una correlazione irragionevole fra istanze di training e di test»; per questo esiste TimeSeriesSplit, dove ogni train è un prefisso temporale del test.
Il leakage per gruppo: quando lo stesso soggetto sta in due mucchi
La terza forma è la più insidiosa, perché sopravvive a una divisione fatta con le regole. Dieci radiografie dello stesso paziente, quaranta ticket dello stesso cliente, cento frasi dello stesso autore: se una parte finisce nel train e una nel test, il modello riconosce il soggetto, non la malattia. La documentazione di scikit-learn porta proprio l’esempio dei dati medici raccolti su più pazienti e indica GroupKFold, che garantisce che uno stesso gruppo non stia in entrambi i lati.
È anche la ragione per cui la preparazione dei dati aziendali va fatta prima della divisione, non dopo: normalizzare o imputare i valori mancanti usando le statistiche di tutto il dataset è leakage a tutti gli effetti, anche quando i mucchi restano formalmente separati.
Cosa resta da sapere: quando i dati sono pochi, e quando dividere a caso è sbagliato
Con cento esempi, il conto di prima mostra il problema: un test da 15 casi dà un intervallo di ±20 punti, e togliere 30 esempi all’addestramento su 100 è uno spreco che si paga in qualità del modello. È il buco che la cross-validation tappa. Si divide il train in k parti, cinque è il valore di default nell’esempio della documentazione, e si addestra k volte, ogni volta tenendo fuori una parte diversa per la valutazione. Alla fine si hanno cinque punteggi: la loro media è la stima, la loro dispersione dice quanto è affidabile. Nell’esempio iris: 0,967, 1,00, 0,967, 0,967, 1,00, media 0,98, deviazione standard 0,02. Il vantaggio è che ogni esempio serve sia per imparare sia per valutare, senza mai fare le due cose nello stesso giro.
La cross-validation sostituisce il validation, non il test
Attenzione a cosa la cross-validation sostituisce: sostituisce il validation, non il test. Il set finale resta fuori, intoccato, e la scelta dell’iperparametro si fa sulla media dei fold. Chi fa cross-validation su tutto il dataset e poi annuncia quel numero come stima di generalizzazione ha ripetuto l’errore iniziale con più passaggi.
Quando dividere train, validation e test a caso è sbagliato
Quando questa spiegazione non vale. Tutto quello che c’è sopra dà per buono che gli esempi siano indipendenti fra loro: solo a quella condizione la divisione casuale è quella giusta. Su serie temporali, su testi dello stesso autore, su immagini dello stesso paziente, il caso è la scelta sbagliata e produce una stima sistematicamente ottimista, lì servono divisione per gruppo o per tempo. E una seconda cautela, che viene dai dati: Recht e colleghi hanno ricostruito da zero i test set di CIFAR-10 e ImageNet e hanno visto crolli di accuratezza del 3, 15% e dell’11, 14%, concludendo però che i cali non erano dovuti al riuso del test set, ma all’incapacità dei modelli di generalizzare su immagini un po’ più difficili (Do ImageNet Classifiers Generalize to ImageNet?). Morale: la divisione in tre mucchi elimina una fonte di illusione, non tutte. Il salto dal laboratorio al mondo resta un problema aperto, e si affronta con il resto della cassetta degli attrezzi, come si valuta un modello sui propri dati, e prima ancora capendo il percorso completo di un modello, dall’ingresso alla risposta.
Fonti:
- scikit-learn, guida alla cross-validation
- Machine Learning Crash Course
- Leakage and the Reproducibility Crisis in ML-based Science
- Do ImageNet Classifiers Generalize to ImageNet?
- Data Leakage — Kaggle Learn, Alexis Cook
Domande frequenti
Che differenza c'è tra validation set e test set?
Il validation set serve a prendere decisioni: quale architettura, quali iperparametri, quando fermare l'addestramento. Il test set non serve a decidere niente e proprio per questo può misurare: si usa una volta sola, alla fine, per stimare come il modello andrà su dati mai visti. Se usi il test per scegliere, quella stima non è più imparziale.
Con quali percentuali si divide un dataset in train, validation e test?
Non esistono percentuali obbligatorie. Il corso ufficiale di Google mostra 70% / 15% / 15% come esempio, ma il vincolo vero è che il test contenga abbastanza esempi per dare un risultato statisticamente significativo. Su 15 esempi di test un solo caso vale 6,7 punti percentuali di accuratezza: con numeri così piccoli la misura è troppo grossolana per decidere.
Cos'è il data leakage e come si evita?
È informazione che filtra dal futuro o dal test verso l'addestramento, e gonfia l'accuratezza in prova senza migliorare nulla in produzione. Le tre forme più comuni: una colonna che contiene di fatto la risposta, una divisione casuale su dati con un ordine temporale, lo stesso soggetto presente sia nel train sia nel test. Si evita con divisioni per tempo o per gruppo e facendo la preparazione dei dati dopo la divisione, non prima.
La cross-validation sostituisce il test set?
No, sostituisce il validation. Si divide il train in k parti e si addestra k volte tenendone fuori una a turno: la media dei punteggi è la stima, la loro dispersione dice quanto è affidabile. Il test set resta fuori e intoccato. Fare cross-validation su tutto il dataset e presentare quel numero come stima di generalizzazione ripete l'errore di partenza.



