Esercizio - Pseudo-etichette con k-NN e regressione logistica
Questa pagina non ha ancora la versione ripasso: qui sotto c'è il testo completo.
In questa pagina 4
Testo (2° appello 2026). Si vuole riconoscere da sensori se un utente fa attività fisica (etichetta ). Le etichette costano e sono rumorose; i dati senza etichetta sono molti. Si hanno: un piccolo insieme etichettato X_train (20 campioni, possibili etichette rumorose o errate), uno grande non etichettato X_unlabeled (786 campioni) e un test X_test (100 campioni). Si propone:
- un classificatore k-NN (distanza euclidea) addestrato sui soli dati etichettati per predire la classe dei non etichettati;
- una misura di confidenza per ogni predizione;
- le predizioni più confidenti diventano pseudo-etichette e si aggiungono al training;
- si addestra una regressione logistica sul dataset esteso.
Domande: implementare il k-NN con confidenza ( tra 3 e 5); completare e addestrare la regressione logistica con discesa del gradiente (a) sui soli dati etichettati e (b) sui dati esteso con i 100 campioni più confidenti per classe; confrontare le predizioni sul test; spiegare perché usare la logistica al posto del k-NN come classificatore finale.
Teoria usata: Classificazione e k-nearest neighborsNella classificazione l'uscita $y$ è una categoria (con $C$ classi; $C=2$ è il caso binario). Il classificatore più semplice è il k-nearest neighbors: una nuova osservazione prende la classe più frequente (voto di maggioranza) tra i suoi $k$ vicini più prossimi nel training, con distanza euclidea $\sqrt{\sum(A_i-B_i)^2}$ o di Manhattan $\sum|A_i-B_i|$ (per la regressione si fa la media dei vicini). $k$ è un iperparametro: $k$ piccolo dà bordi frastagliati e overfitting, $k$ grande underfitting. È un metodo basato su istanze e «pigro» (nessun addestramento, costo alla predizione), sensibile a scala e feature irrilevanti e alla maledizione della dimensionalità; gli ingressi categorici si codificano con one-hot. Approfondimento: non nel programma di Telecomunicazioni.Classificazione e k-nearest neighbors → (k-NN, distanza); Regressione logistica e softmaxLa regressione lineare non è adatta alla classificazione (valori fuori da [0,1], retta tirata dai punti lontani). La regressione logistica passa il predittore lineare dalla sigmoide $\sigma(z)=1/(1+e^{-z})$ e interpreta $\hat y=\sigma(x^T\beta)$ come $P(y=1\mid x)$: si predice la classe 1 se $\hat y\ge0{,}5$, cioè $x^T\beta\ge0$ (bordo lineare). L'errore quadratico dà una funzione non convessa; si usa la log-verosimiglianza negativa $-\sum[y\log\hat y+(1-y)\log(1-\hat y)]$, convessa, con gradiente $X^T(\hat y-y)$ e nessuna formula chiusa (discesa del gradiente). Per più classi: one-vs-one ($C(C-1)/2$ classificatori, voto), one-vs-all ($C$ classificatori, massima probabilità), o la softmax $p_c=e^{z_c}/\sum_ke^{z_k}$ con cross-entropia. Si può regolarizzare (ridge, LASSO, Elastic Net) e la cross-validation si fa stratificata. Approfondimento: non nel programma di Telecomunicazioni.Regressione logistica e softmax → (sigmoide, gradiente ); Metriche di classificazioneIn classificazione binaria ogni previsione è vero positivo (TP), vero negativo (TN), falso positivo (FP, errore di tipo I) o falso negativo (FN, errore di tipo II). Da queste quattro quantità: accuracy $=\frac{TP+TN}{TP+TN+FP+FN}$, specificità $=\frac{TN}{TN+FP}$, precision $=\frac{TP}{TP+FP}$, recall $=\frac{TP}{TP+FN}$, e la loro media armonica $F_1=\frac{2PR}{P+R}$. Con dati sbilanciati l'accuracy inganna (un modello che predice sempre la classe maggioritaria ha 99%): si usano precision, recall, F1, ROC-AUC, la cross-validation stratificata e il riequilibrio con undersampling o oversampling (non SMOTE). Cambiando la soglia sulla probabilità si ottiene la curva ROC (TPR contro FPR) e l'area AUC. Approfondimento: non nel programma di Telecomunicazioni.Metriche di classificazione → (matrice di confusione); LASSO e discesa del gradienteIl LASSO è la regressione regolarizzata con penalità $L_1$: minimizza $\sum_i(y_i-x_i^T\beta)^2+\lambda\sum_{j\ge1}|\beta_j|$. A differenza della ridge, porta alcuni coefficienti esattamente a zero (soluzione sparsa, selezione delle feature): geometricamente le curve di livello dell'errore toccano il vincolo $\sum|\beta_j|\le s$ (un rombo) in uno spigolo. Non ha formula chiusa, quindi si minimizza con la discesa del gradiente $W\leftarrow W-\eta,\nabla J(W)$, usando il subgradiente $\operatorname{sign}(\beta_j)$ per il valore assoluto (nel punto 0 qualunque valore in $[-1,1]$). Il passo $\eta$ è critico: per l'errore quadratico converge se $\eta<1/\mu_{\max}(X^TX)$; si può usare $\eta_t=\eta_0/(1+\gamma t)$. L'Elastic Net combina le penalità $L_1$ e $L_2$ con $\lambda_1=\alpha\lambda$, $\lambda_2=(1-\alpha)\lambda$.LASSO e discesa del gradiente → (passo adattivo).
1-2. k-NN con confidenza
Per ogni punto non etichettato: distanze da tutti i 20 punti etichettati, indici dei più vicini, classe di maggioranza e come confidenza la frazione di vicini che votano per la classe vincente. Con la confidenza può valere solo (3 voti su 5), o (5 su 5).
def knn_with_confidence(X_train, y_train, X_test, k):
d = np.sqrt(((X_test[:, None] - X_train[None]) ** 2).sum(axis=2))
nearest = np.argsort(d, axis=1)[:, :k]
votes = y_train.ravel()[nearest] # (n_test, k)
p1 = votes.mean(axis=1) # frazione di vicini di classe 1
pred = (p1 > 0.5).astype(int)
conf = np.where(pred == 1, p1, 1 - p1) # confidenza = frazione per la classe vincente
return pred.reshape(-1, 1), conf.reshape(-1, 1)Sui 786 punti non etichettati si ottengono predizioni di classe 0 e di classe 1; le confidenze sono per punti, per e per . Osservazione: poiché la confidenza ha solo tre valori, la selezione dei «100 più confidenti per classe» fra molti punti con confidenza è decisa dall'ordine con cui argsort rompe i pareggi: una confidenza più fine si ottiene con un ensemble di k-NN, ognuno su un sottoinsieme casuale del training, e la confidenza è la frazione di modelli che votano per la classe vincente (soluzione alternativa proposta dall'appello).
3. Pseudo-etichette
Per ciascuna classe predetta si prendono i 100 campioni a confidenza massima, con la loro classe predetta come etichetta, e si aggiungono ai 20 etichettati: il dataset esteso ha campioni. Si sfrutta così la struttura dei dati non etichettati (due nubi di punti).
4. Regressione logistica
def train_logreg(X, y, lr0, decay, n_iter):
X = np.hstack([np.ones((len(X), 1)), X]); beta = np.random.rand(X.shape[1], 1)
for i in range(n_iter):
lr = lr0 / (1 + decay * i)
y_hat = 1 / (1 + np.exp(-X @ beta))
beta -= lr * X.T @ (y_hat - y) / len(y) # gradiente della log-verosimiglianza media
return beta(con , decadimento , 1000 iterazioni).
Risultati sul test (100 campioni, 50 per classe; righe: classe vera, colonne: prevista):
| addestramento | matrice di confusione | accuracy |
|---|---|---|
| solo 20 etichettati | ||
| con 200 pseudo-etichette |
Con i soli 20 campioni il bordo è mal posizionato: tutti i campioni di classe 1 sono giusti ma campioni su di classe 0 sono classificati come 1. Nei dati di training le due classi sono vicine (medie e ) e la classe 1 del test è molto più lontana (media della prima coordinata circa ): con 20 punti il modello non conosce la geometria del problema. Le pseudo-etichette, grazie ai dati non etichettati, mostrano dove sono le due nubi e correggono il bordo: errore zero sul test. Lo pseudo-labeling migliora quindi la regressione logistica in questo caso, a patto che il classificatore iniziale sia abbastanza buono sui campioni più confidenti (se le pseudo-etichette fossero sbagliate, il modello imparerebbe gli stessi errori: confirmation bias).
Perché la logistica come classificatore finale
- Costo di inferenza e memoria. Il k-NN deve calcolare le distanze da tutti i campioni di training a ogni previsione e conservare tutto il training; la logistica, una volta noto , richiede un prodotto scalare e conserva solo numeri. È decisivo se l'inferenza dev'essere veloce o su dispositivi piccoli (come uno smartwatch).
- Interpretabilità. I coefficienti dicono quali feature pesano di più e con quale segno; il k-NN non ha un modello esplicito.
- Fornisce una probabilità (con un bordo lineare liscio) invece di una semplice frazione di vicini.