Salta al contenuto
Note per Studenti Esercizio - SVM con tre kernel sul dataset iris (laboratorio 10)

Esercizio - SVM con tre kernel sul dataset iris (laboratorio 10)

Teoria: Apprendimento automatico nell'IA - supervisionato, SVM e valutazioneQuadro del machine learning nel corso di IA. Tre forme di apprendimento: supervisionato (coppie ingresso-uscita, classificazione se l'uscita è discreta e regressione se è un numero), non supervisionato (pattern senza feedback, per esempio clustering) e per rinforzo (ricompense). Un'ipotesi h approssima la funzione vera f e si valuta sul test set, non sul training set: un modello troppo semplice ha bias alto (underfitting), uno troppo complesso varianza alta (overfitting). Servono training, validation e test set; con pochi dati si usa la k-fold cross-validation. Alberi di decisione: si sceglie l'attributo con massimo guadagno d'informazione Gain = B(p/(p+n)) - somma (Nk/N) B(pk/Nk), si pota con il test del chi quadro (Delta > Delta*), si riduce la varianza con bagging e random forest. Perdita L1 e L2, regressione lineare e discesa del gradiente w <- w - alpha dL/dw. SVM: separatore a margine massimo, vettori di supporto, kernel trick con K(xj,xk). Pipeline scikit-learn del laboratorio 10: load_digits, train_test_split, SVC(C, kernel, gamma), fit, predict, classification_report, confusion_matrix, cross_val_score.Apprendimento automatico nell'IA - supervisionato, SVM e valutazione →, sezioni 6 e 7; kernel in Support vector machines e metodi kernelUna SVM cerca l'iperpiano $w\cdot x+b=0$ che separa due classi con il margine più largo possibile: normalizzando $y_i(w\cdot x_i+b)\ge1$ il margine totale vale $2/|w|$, quindi si risolve $\min\frac12|w|^2$ (problema convesso, nessun minimo locale). Con classi sovrapposte si ammettono errori con le variabili di scarto $\xi_i$ e il parametro $C$ (soft margin, equivalente alla hinge loss più una penalità su $|w|^2$); $C$ piccolo = margine largo e più bias, $C$ grande = margine stretto e più varianza, si sceglie per cross-validation. La soluzione dipende solo dai vettori di supporto ($w=\sum\alpha_iy_ix_i$) e solo tramite prodotti scalari, per questo si può sostituire $x_i\cdot x_j$ con un kernel $K(x_i,x_j)=\langle\phi(x_i),\phi(x_j)\rangle$ (polinomiale, RBF) senza calcolare $\phi$: così si ottengono bordi non lineari. La SVR usa lo stesso schema con un tubo di tolleranza $\varepsilon$. Nell'esame le SVM sono solo nella parte teorica.Support vector machines e metodi kernel → e Esercizio - Kernel e confronto tra SVM; matrice di confusione in 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 →.

Testo. Caricare il dataset iris tra quelli disponibili in scikit-learn.

(a) Verificare le proprietà del dataset (numero di campioni, numero di classi, ...) come si è fatto a lezione con il dataset digits. (b) Dividere il dataset in training e test con le percentuali 70% - 30%. (c) Addestrare una SVM con kernel diversi (lineare, rbf, polinomiale) lasciando i valori predefiniti degli iperparametri. (d) Testare i modelli ottenuti sul test set. (e) Rappresentare le prestazioni di ciascun kernel con una matrice di confusione. Commentare i risultati su training e test con i diversi kernel.

Soluzione

(a) Proprietà del dataset

python
import numpy as np
from sklearn import datasets, svm, metrics
from sklearn.model_selection import train_test_split

iris = datasets.load_iris()
X, y = iris.data, iris.target
print(X.shape)                                   # (150, 4)
print(np.unique(y), len(np.unique(y)))           # [0 1 2] 3
print(X[0])                                      # [5.1 3.5 1.4 0.2]
print([int(np.sum(y == c)) for c in range(3)])   # [50, 50, 50]

Output: 150 campioni, 4 attributi, 3 classi equilibrate (50 per classe: Iris-setosa, Iris-versicolour, Iris-virginica). I quattro attributi sono lunghezza e larghezza del sepalo e lunghezza e larghezza del petalo, in cm: il primo campione è (5,1; 3,5; 1,4; 0,2)(5{,}1;\ 3{,}5;\ 1{,}4;\ 0{,}2). y ha forma (150,)(150,).

(b) Divisione 70% - 30%

test_size=0.30 dà 105105 campioni di training e 4545 di test. Serve shuffle=True: il dataset è ordinato per classe (prima 50 della classe 0, poi 50 della 1, poi 50 della 2), e senza rimescolare gli ultimi 45 campioni sono tutti della classe 2: il test conterrebbe una sola classe (verificato: np.unique(y_test) =[2]=[2], 45 elementi).

python
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30, shuffle=True, random_state=0)
print(len(X_train), len(X_test), np.unique(y_train), np.unique(y_test))   # 105 45 [0 1 2] [0 1 2]

(random_state=0 rende il risultato riproducibile: il corso non lo fissa e le cifre cambiano a ogni esecuzione.)

(c), (d), (e) Tre kernel

python
for kernel in ("linear", "rbf", "poly"):
    clf = svm.SVC(kernel=kernel)                  # C=1, gamma='scale', degree=3 (valori predefiniti)
    clf.fit(X_train, y_train)
    predicted = clf.predict(X_test)
    print("Accuracy kernel", kernel, ":", metrics.accuracy_score(y_test, predicted))
    print(metrics.confusion_matrix(y_test, predicted))

Con random_state=0 si ottiene, per tutti e tre i kernel, accuratezza 0,97780{,}9778 (4444 test su 4545) e la stessa matrice di confusione (righe = classe vera, colonne = predetta): (160001710011).\begin{pmatrix}16&0&0\\0&17&1\\0&0&11\end{pmatrix}. L'unico errore è un campione della classe 1 (versicolour) classificato come classe 2 (virginica): precision della classe 2 1112=0,917\tfrac{11}{12}=0{,}917, recall della classe 1 1718=0,944\tfrac{17}{18}=0{,}944; la classe 0 (setosa) è separata perfettamente (precision e recall 11).

Il corso, con una divisione diversa (non fissata), riporta:

kernel accuratezza matrice di confusione
lineare 0,93330{,}9333 (120001020120)\left(\begin{smallmatrix}12&0&0\\0&10&2\\0&1&20\end{smallmatrix}\right)
rbf 0,91110{,}9111 (120001110318)\left(\begin{smallmatrix}12&0&0\\0&11&1\\0&3&18\end{smallmatrix}\right)
poly 0,93330{,}9333 (120001020120)\left(\begin{smallmatrix}12&0&0\\0&10&2\\0&1&20\end{smallmatrix}\right)

(Lo schema è lo stesso: la classe 0 è sempre perfetta, gli errori sono tra le classi 1 e 2. 0,9333=42/450{,}9333=42/45, 0,9111=41/450{,}9111=41/45.) I numeri del corso non si riproducono perché dipendono dal rimescolamento: il corso lo dice esplicitamente.

Commento

Le prestazioni dei tre kernel sono confrontabili. Una prova più solida della singola divisione: ripetendo la divisione 70-30 con 200 valori diversi di random_state e facendo la media, l'accuratezza è 0,9740{,}974 (lineare, deviazione standard 0,0220{,}022), 0,9560{,}956 (rbf, 0,0260{,}026) e 0,9650{,}965 (poly, 0,0240{,}024): le differenze tra kernel sono più piccole della variabilità da una divisione all'altra. In questi casi si preferisce il modello più semplice, cioè il kernel lineare (meno iperparametri, meno rischio di overfitting): è il rasoio di Ockham. I dati di iris sono quasi linearmente separabili (la setosa è nettamente separata; versicolour e virginica si sovrappongono un poco), quindi un confine non lineare non porta vantaggi.

Per commentare anche il training basta clf.score(X_train, y_train): con random_state=0 vale 0,9810{,}981 (lineare), 0,9710{,}971 (rbf) e 0,9900{,}990 (poly), cioè poco diverso dal test; una grande differenza tra training e test sarebbe segno di overfitting.

Versione ripasso

Teoria: Apprendimento automatico nell'IA - supervisionato, SVM e valutazioneQuadro del machine learning nel corso di IA. Tre forme di apprendimento: supervisionato (coppie ingresso-uscita, classificazione se l'uscita è discreta e regressione se è un numero), non supervisionato (pattern senza feedback, per esempio clustering) e per rinforzo (ricompense). Un'ipotesi h approssima la funzione vera f e si valuta sul test set, non sul training set: un modello troppo semplice ha bias alto (underfitting), uno troppo complesso varianza alta (overfitting). Servono training, validation e test set; con pochi dati si usa la k-fold cross-validation. Alberi di decisione: si sceglie l'attributo con massimo guadagno d'informazione Gain = B(p/(p+n)) - somma (Nk/N) B(pk/Nk), si pota con il test del chi quadro (Delta > Delta*), si riduce la varianza con bagging e random forest. Perdita L1 e L2, regressione lineare e discesa del gradiente w <- w - alpha dL/dw. SVM: separatore a margine massimo, vettori di supporto, kernel trick con K(xj,xk). Pipeline scikit-learn del laboratorio 10: load_digits, train_test_split, SVC(C, kernel, gamma), fit, predict, classification_report, confusion_matrix, cross_val_score.Apprendimento automatico nell'IA - supervisionato, SVM e valutazione →, Support vector machines e metodi kernelUna SVM cerca l'iperpiano $w\cdot x+b=0$ che separa due classi con il margine più largo possibile: normalizzando $y_i(w\cdot x_i+b)\ge1$ il margine totale vale $2/|w|$, quindi si risolve $\min\frac12|w|^2$ (problema convesso, nessun minimo locale). Con classi sovrapposte si ammettono errori con le variabili di scarto $\xi_i$ e il parametro $C$ (soft margin, equivalente alla hinge loss più una penalità su $|w|^2$); $C$ piccolo = margine largo e più bias, $C$ grande = margine stretto e più varianza, si sceglie per cross-validation. La soluzione dipende solo dai vettori di supporto ($w=\sum\alpha_iy_ix_i$) e solo tramite prodotti scalari, per questo si può sostituire $x_i\cdot x_j$ con un kernel $K(x_i,x_j)=\langle\phi(x_i),\phi(x_j)\rangle$ (polinomiale, RBF) senza calcolare $\phi$: così si ottengono bordi non lineari. La SVR usa lo stesso schema con un tubo di tolleranza $\varepsilon$. Nell'esame le SVM sono solo nella parte teorica.Support vector machines e metodi kernel →.

Procedura. load_iris(): XX con forma (150,4)(150,4), 3 classi da 50 campioni (setosa, versicolour, virginica), attributi: lunghezza e larghezza di sepalo e petalo. train_test_split(X, y, test_size=0.30, shuffle=True): 105 training e 45 test. Per ogni kernel (linear, rbf, poly): SVC(kernel=k).fit(...), predict, accuracy_score, confusion_matrix.

  • shuffle=True è necessario: il dataset è ordinato per classe; senza rimescolare il test (ultimi 45) contiene solo la classe 2.
  • Con random_state=0 i tre kernel danno tutti 0,97780{,}9778 (44/4544/45), matrice (160001710011)\left(\begin{smallmatrix}16&0&0\\0&17&1\\0&0&11\end{smallmatrix}\right): un solo errore, versicolour classificata virginica.
  • Risultati del corso (divisione diversa): lineare 0,93330{,}9333, rbf 0,91110{,}9111, poly 0,93330{,}9333; gli errori sono sempre tra le classi 1 e 2, la classe 0 è perfetta. Non si riproducono, dipendono dal rimescolamento.
  • Media su 200 divisioni: lineare 0,9740{,}974, rbf 0,9560{,}956, poly 0,9650{,}965 (dev. standard ≈0,025\approx0{,}025): differenze minori della variabilità.
  • Conclusione: a prestazioni confrontabili si sceglie il modello più semplice, il kernel lineare (rasoio di Ockham).
python
for kernel in ("linear", "rbf", "poly"):
    clf = svm.SVC(kernel=kernel).fit(X_train, y_train)
    print(kernel, metrics.accuracy_score(y_test, clf.predict(X_test)))

Errori tipici: shuffle=False su un dataset ordinato; confrontare i kernel su una sola divisione; commentare le cifre del corso come se fossero riproducibili.

Teoria collegata