7.18.2 EP07_02 🟡 Normalizzazione Z-score e Robustezza del k-NN a Scale Diverse
Questo esercizio riprende il classificatore implementato nell’EP07_01, questa volta sotto la prospettiva discussa nella sezione L’Impatto della Scala e la Normalizzazione delle Caratteristiche del capitolo: il k-NN decide in base alla distanza tra vettori, per cui una caratteristica misurata su una scala molto più ampia rispetto alle altre tende a dominare il calcolo della distanza, anche quando non è la più rilevante per separare le classi.
Un sistema di ispezione registra, per ogni pezzo, la sua area (in pixel, che può arrivare a centinaia o migliaia) e la sua circolarità (sempre tra \(0\) e \(1\)). Ti è stato affidato il compito di classificare nuovi pezzi tramite k-NN in due modi — con e senza la standardizzazione Z-score presentata nel capitolo — e di riportare in quali casi i due approcci divergono.
7.18.2.1 📋 Linee Guida di Implementazione
- Quantità e parametro: Leggere l’intero \(N\) (numero di esempi di addestramento) e l’intero dispari \(k\).
- Esempi di addestramento: Per ciascuno degli \(N\) esempi, leggere tre valori: l’area \(x_1\) (reale), la circolarità \(x_2\) (reale) e l’etichetta \(r\) (intero, \(0\) o \(1\)).
- Query: Leggere l’intero \(Q\) e, successivamente, le coordinate \(x_1, x_2\) di ciascuna query.
- Classificazione senza normalizzazione: Per ogni query, classificarla tramite k-NN direttamente su \((x_1, x_2)\), con distanza euclidea e le stesse regole di pareggio dell’EP07_01 (ordine di lettura per distanze a pari merito; vicino più prossimo tra classi a pari merito nella votazione).
- Parametri di normalizzazione: Calcolare la media \(\mu_j\) e la deviazione standard popolazionale \(\sigma_j\) (divisione per \(N\), non per \(N-1\) — la stessa convenzione adottata dalla classe
StandardScaler) di ciascuna caratteristica \(j \in \{1,2\}\), esclusivamente sul set di addestramento. - Standardizzazione: Trasformare ciascuna caratteristica di addestramento e di query tramite \[ z_j = \frac{x_j - \mu_j}{\sigma_j}. \] Se \(\sigma_j = 0\) (caratteristica costante nell’addestramento), definire \(z_j = 0\) per tutti i campioni di quella caratteristica, evitando la divisione per zero.
- Classificazione con normalizzazione: Ripetere la classificazione k-NN del punto 4, ora sui vettori standardizzati \((z_1, z_2)\), con le stesse regole di pareggio.
- Output: Per ogni query, nell’ordine di input, stampare le due classi previste. Alla fine, stampare il numero di query in cui le due classificazioni divergono.
7.18.2.2 📌 Vincoli Computazionali
- Adattamento solo sul training: \(\mu_j\) e \(\sigma_j\) sono calcolati unicamente a partire dal set di addestramento e riapplicati alle query — mai ricalcolati a partire da esse. Questa pratica evita la dispersione dei dati (data leakage), menzionata nella sezione sulla normalizzazione del capitolo.
- Deviazione standard popolazionale: utilizzare \(\sigma_j = \sqrt{\frac{1}{N}\sum_i (x_{i,j}-\mu_j)^2}\), e non la versione campionaria (divisione per \(N-1\)).
- Caratteristica costante: trattare \(\sigma_j = 0\) come caso speciale (punto 6); non deve verificarsi un errore di divisione per zero.
- Regole di pareggio: riutilizzare esattamente le convenzioni dell’EP07_01, sia nella selezione dei \(k\) vicini che nella votazione a maggioranza.
7.18.2.3 🧠 Fondamenti Teorici
| Elemento | Ruolo |
|---|---|
| Standardizzazione Z-score | Riscalare ogni caratteristica a media \(0\) e deviazione standard \(1\), rendendo scale eterogenee comparabili |
| Adattamento (fit) solo sul training | Garantisce che la valutazione sulle query rifletta solo ciò che il modello ha appreso nell’addestramento |
| Distanza euclidea senza normalizzazione | Dominata dalla caratteristica con maggiore ampiezza — qui, l’area |
| Predizione divergente | Evidenzia che la scala delle caratteristiche, e non solo l’algoritmo o i dati, può determinare il confine decisionale del k-NN |
Questo esercizio sottolinea, in modo controllato, la ragione per cui lo StandardScaler viene applicato prima del k-NN nel corso del capitolo: senza questo passaggio, caratteristiche come la circolarità — anche se altamente discriminative — possono essere praticamente ignorate dal classificatore di fronte a una caratteristica come l’area con ampiezza centinaia di volte maggiore.
7.18.2.4 📦 Specifica di Input e Output (VPL)
Input:
- Riga 1: Interi \(N\) e \(k\), separati da spazio.
- Prossime \(N\) righe: tre valori per riga — \(x_1\), \(x_2\) (reali) e \(r\) (intero \(\in \{0,1\}\)), separati da spazio.
- Prossima riga: intero \(Q\).
- Prossime \(Q\) righe: due valori per riga — \(x_1\), \(x_2\) (reali) della query, separati da spazio.
Output:
- \(Q\) righe, nel formato
SemNorm=<0|1> ComNorm=<0|1>, nell’ordine di input delle query. - Ultima riga:
Divergiu: <int>.
7.18.2.5 📌 Esempi
| Input | Output | Osservazione |
|---|---|---|
| 4 3 10 0.9 0 12 0.85 0 900 0.2 1 950 0.25 1 1 500 0.88 |
SemNorm=1 ComNorm=0 Divergiu: 1 |
Senza normalizzazione, l’area (scala di centinaia) domina la distanza e la query viene classificata come classe 1. Dopo la standardizzazione, la circolarità — molto più vicina ai campioni di classe 0 — inizia a pesare in modo confrontabile, e la predizione cambia a 0. |
| 2 1 0 0.5 0 100 0.5 1 1 60 0.5 |
SemNorm=1 ComNorm=1 Divergiu: 0 |
La circolarità è costante nell’addestramento (\(\sigma_2=0\)); secondo la regola del punto 6, \(z_2=0\) per tutti i campioni, e la classificazione dipende solo dall’area in entrambi i casi. |
%%writefile EP07_02.py
# Codice PythonOverwriting EP07_02.py
TestSuite("EP07_02.py").run()✔️ EP07_02.cases esiste già in casos/
📋 5 caso/i caricato/i da casos/EP07_02.cases
🔍 Test di Python: EP07_02.py
⚠️ EP07_02.py: file vuoto (meno di 3 righe). Test saltati.