La domanda nascosta dentro un risultato eccellente
Un sistema di ispezione riconosce correttamente quasi tutte le immagini tenute fuori dall’addestramento. Sembra pronto per una nuova linea produttiva. Ma le immagini di prova provengono dalle stesse macchine già viste: illuminazione, sfondo e geometria dell’acquisizione sono familiari. Abbiamo misurato la capacità di riconoscere il difetto, oppure quella di riconoscere il contesto? La risposta dipende da come abbiamo costruito la prova, prima ancora che dall’architettura del modello.
Abstract. Costruiamo un controesempio controllato: un classificatore che ricorda soltanto l’identità della macchina ottiene il 100% con una divisione casuale delle osservazioni e il 50% quando incontra macchine nuove. Non è un benchmark di visione: nessuna immagine viene elaborata. Il modello volutamente elementare permette di isolare la domanda statistica. Deriviamo la probabilità di sovrapposizione, leggiamo le matrici di confusione e distinguiamo valutazione su macchine note, macchine nuove e tempi futuri. Il lettore imparerà a riconoscere quale promessa un punteggio può davvero sostenere.
Prima del test: che cosa deve essere nuovo?
L’addestramento usa esempi con risposta nota per costruire una regola; il test applica quella regola a esempi esclusi da questa costruzione. Una riga diversa nel file non è necessariamente una nuova situazione. Venti fotogrammi della stessa acquisizione condividono condizioni che due macchine possono non condividere. Chiamiamo gruppo l’insieme delle osservazioni legate alla stessa unità di interesse: qui una macchina. Il gruppo non è una classe. La classe è la risposta da prevedere, per esempio 0 oppure 1; un gruppo può in generale contenere entrambe.
Se il servizio lavorerà sulle cento macchine già installate, conoscere alcune loro caratteristiche può essere legittimo. Se deve essere venduto a uno stabilimento mai osservato, il test deve rappresentare questa assenza di familiarità. Sono due obiettivi diversi, non una graduatoria morale tra procedure. Scrivere “accuratezza 98%” senza specificare l’unità lasciata fuori nasconde proprio questa distinzione. Anche una separazione per macchina può essere insufficiente se tutte le macchine condividono lo stesso stabilimento e la promessa riguarda stabilimenti nuovi.
Un modello che non sa nulla dei difetti
Generiamo cento identificativi e assegniamo casualmente cinquanta etichette 0 e cinquanta etichette 1. Ogni macchina produce venti righe con la stessa etichetta: duemila righe in totale. La costanza dell’etichetta all’interno della macchina è un’ipotesi deliberatamente estrema, utile a rendere evidente la scorciatoia. Non sostiene che i difetti reali siano costanti. Ogni riga conserva macchina, indice del fotogramma ed etichetta; non contiene pixel né caratteristiche del pezzo.
Il classificatore crea un dizionario: identificativo → etichetta osservata. Per un identificativo sconosciuto restituisce la classe più frequente nell’addestramento, scegliendo 0 in caso di parità. Costruire il dizionario richiede un passaggio sui dati; la previsione consulta una chiave, senza apprendere alcuna relazione trasferibile tra aspetto e difetto. Il costo medio della consultazione è costante per un dizionario hash, mentre memoria e costruzione crescono con gruppi e righe. È una baseline diagnostica, non un’architettura proposta per la produzione.
Perché la divisione casuale rende quasi certa la familiarità
Assegniamo ogni riga all’addestramento con probabilità p = 0,8, indipendentemente dalle altre. Consideriamo una riga che sappiamo essere nel test. Se il suo gruppo contiene m righe, restano m − 1 occasioni per vedere la stessa macchina nell’addestramento. Per non vederla mai, tutte queste righe devono finire nel test. Moltiplichiamo le probabilità perché le assegnazioni sono indipendenti; poi sottraiamo da uno per ottenere il caso opposto.
P(non vista) = 0.2^19 = 5.24288 × 10^−14
Con una sola riga per macchina, la probabilità di averla già vista è zero; con due righe è 80%; con cinque è 99,84%. Con venti è praticamente uno. Questi valori riguardano la procedura di divisione, non la probabilità che il modello risponda correttamente. Per il nostro dizionario, tuttavia, conoscere il gruppo basta a conoscere la risposta. Aumentare i fotogrammi rende il test più familiare anche se non aggiunge alcuna conoscenza su una nuova macchina. La formula usa assegnazioni Bernoulli indipendenti: una divisione con numero di righe fissato esattamente richiede un conteggio combinatorio diverso.
Due protocolli, due risultati realmente eseguiti
Nell’esperimento Python con seed 20260929 la divisione delle righe produce 1.577 esempi di addestramento e 423 di test. Tutte le cento macchine compaiono in entrambi gli insiemi. Le 423 risposte sono corrette: accuratezza 1. Nel secondo protocollo scegliamo invece dieci macchine di classe 0 e dieci di classe 1 da riservare interamente al test. Le altre ottanta forniscono 1.600 righe di addestramento. Nessuno dei venti identificativi di prova è noto al dizionario: tutte le 400 previsioni usano il fallback 0 e soltanto 200 sono corrette.
| Protocollo | Righe train/test | Gruppi condivisi | Accuratezza |
|---|---|---|---|
| row Bernoulli p=0.8 | 1577 / 423 | 100 | 100% |
| held-out groups | 1600 / 400 | 0 | 50% |
La matrice di confusione rende il secondo risultato più informativo del solo 50%. Le righe della matrice sono le classi vere 0 e 1, le colonne le previsioni 0 e 1. Otteniamo [[200, 0], [200, 0]]: riconosciamo tutti gli zeri e nessun uno. Non è una capacità “mediamente discreta”; è la conseguenza di rispondere sempre allo stesso modo. La prima matrice è [[207, 0], [0, 216]]. Entrambe sono salvate nel JSON, insieme a etichette, gruppi esclusi e indici delle righe, così il risultato non dipende da una descrizione verbale incompleta.

Che cosa dimostra il controesempio, e che cosa non dimostra
Abbiamo dimostrato che separare le righe non basta, in generale, a dimostrare generalizzazione tra gruppi. Non abbiamo dimostrato che ogni rete neurale memorizzi la macchina, né che il 50% sia il risultato atteso di qualsiasi sistema industriale. Un modello che apprende caratteristiche del difetto può funzionare anche su gruppi nuovi. Il controesempio confuta una deduzione: “nessuna riga di test era nel training, quindi abbiamo verificato l’uso su macchine nuove”. Per confutarla basta un caso eseguito in cui premessa vera e conclusione falsa convivono.
Le etichette bilanciate del test per gruppi sono una scelta esplicita per isolare la memoria. Un impianto reale potrebbe avere prevalenze diverse e gruppi di dimensioni molto diverse. La media per fotogramma pesa di più le macchine che producono più immagini; la media delle accuratezze per macchina assegna invece lo stesso peso a ogni macchina. Nessuna delle due è universalmente corretta: devono corrispondere alla decisione da supportare. Nel nostro caso venti righe per gruppo rendono uguali le due medie, ma questa coincidenza non si trasferisce automaticamente ai dati reali.
Dalla dimostrazione al progetto di una prova
Per verificare una macchina nuova si decide prima quali macchine riservare, poi si costruiscono i dati di training e test. Trasformazioni dello stesso originale devono restare dallo stesso lato: ritagliare o aumentare un’immagine prima di dividerla può disseminare quasi copie nei due insiemi. Anche normalizzazione e selezione delle caratteristiche devono essere apprese sul solo training, ripetendo la stima dentro ogni partizione usata per scegliere il modello. L’ordine delle operazioni fa parte del metodo, non è una semplice precauzione amministrativa.
La documentazione scikit-learn descrive GroupKFold, che mantiene separati i gruppi, e StratifiedGroupKFold, che tenta anche di conservare le proporzioni delle classi. Questi strumenti non scelgono quale gruppo abbia significato per il problema. Nell’esperimento abbiamo implementato direttamente una sola divisione per gruppi bilanciata, senza eseguire scikit-learn né una validazione incrociata. La validazione incrociata ripete training e valutazione su partizioni diverse; può aiutare a scegliere impostazioni del modello, ma i gruppi del test finale devono restare estranei a quella scelta.
Resta la dimensione temporale. Una macchina nota domani può avere un utensile usurato, una telecamera sostituita o nuove condizioni di produzione. Una divisione casuale di fotogrammi passati non misura necessariamente queste transizioni. Se la promessa è “funziona domani sulle macchine attuali”, serve una prova che rispetti l’ordine temporale. Se è “funziona domani in uno stabilimento nuovo”, occorre rappresentare entrambe le differenze. Non esiste una divisione universale che renda irrilevante la descrizione del contesto operativo.
Infine, quattrocento fotogrammi provenienti da venti macchine non sono quattrocento dimostrazioni indipendenti di trasferibilità. Se vogliamo quantificare l’incertezza tra macchine, dobbiamo preservare i gruppi anche nel ricampionamento, e ricordare che venti unità possono non rappresentare varianti rare. Qui non calcoliamo intervalli di confidenza né stimiamo prestazioni di popolazione: il risultato è un controesempio determinato dal dataset e dal protocollo salvati. Ripetere lo stesso esperimento rende verificabile il calcolo, non amplia la popolazione osservata.
La risposta: contare le novità, non soltanto le righe
Mille immagini possono essere preziose per descrivere una macchina, ma non equivalgono automaticamente a mille prove su macchine nuove. Il dizionario ha raggiunto il 100% senza imparare nulla sui difetti: questo è il punto da ricordare quando leggiamo un benchmark. Una valutazione utile dichiara che cosa resta familiare e che cosa cambia, sceglie la divisione di conseguenza e interpreta il punteggio entro quel perimetro. La domanda iniziale non si risolve aumentando il numero di immagini: si risolve allineando la prova alla promessa.
Fonti e riproducibilità
Il frammento seguente riduce il dizionario a quattro macchine per mostrarne il meccanismo. L’archivio contiene invece le cento macchine, il seed, tutte le assegnazioni e i risultati riportati sopra, eseguiti con la libreria standard Python. Non sono prove di un prodotto EL-AI né risultati ottenuti su immagini industriali. Il riferimento documentale descrive i separatori disponibili; il dataset, la derivazione della probabilità e il controesempio sono analisi didattica di questo articolo.
def predict(train, test):
memory = {group: label for group, label in train}
return [memory.get(group, 0) for group, _ in test]
train = [('A', 0), ('B', 1)]
for test in [[('A', 0), ('B', 1)], [('C', 0), ('D', 1)]]:
predictions = predict(train, test)
accuracy = sum(p == y for p, (_, y) in zip(predictions, test))/len(test)
print(predictions, accuracy)
Codice, dati e istruzioni · JSON. Calcoli didattici eseguiti con Python 3.14.0; figure con Matplotlib 3.11.2. Analisi con assistenza AI, senza dichiarare peer review o revisione umana. Copertina originale ImageGen, illustrativa: non documenta persone, sedi o installazioni EL-AI. Fonti consultate il 29 settembre 2026.

