Una gentile introduzione alle Support Vector Machines

Introduzione alle SVM

 

Le macchine a vettori di supporto, comunemente chiamate SVM, sono una classe di algoritmi di apprendimento automatico semplici ma potenti utilizzati sia per la classificazione che per la regressione. In questa discussione, ci concentreremo sull’uso delle macchine a vettori di supporto per la classificazione.

Inizieremo esaminando le basi della classificazione e degli iperpiani che separano le classi. Successivamente, passeremo ai classificatori a margine massimo, costruendo gradualmente le macchine a vettori di supporto e l’implementazione dell’algoritmo con scikit-learn.

 

Problema di classificazione e iperpiani separanti

 

La classificazione è un problema di apprendimento supervisionato in cui abbiamo punti dati etichettati e l’obiettivo dell’algoritmo di apprendimento automatico è prevedere l’etichetta di un nuovo punto dati. 

Per semplicità, prendiamo in considerazione un problema di classificazione binaria con due classi, chiamate classe A e classe B. E dobbiamo trovare un iperpiano che separi queste due classi. 

Matematicamente, un iperpiano è uno spazio vettoriale la cui dimensione è una in meno rispetto allo spazio ambiente. Ciò significa che se lo spazio ambiente è una linea, l’iperpiano è un punto. E se lo spazio ambiente è un piano bidimensionale, l’iperpiano è una linea, e così via.

Quindi, quando abbiamo un iperpiano che separa le due classi, i punti dati appartenenti alla classe A si trovano da un lato dell’iperpiano. E quelli appartenenti alla classe B si trovano dall’altro lato.

Pertanto, nello spazio unidimensionale, l’iperpiano separatore è un punto:

   

In due dimensioni, l’iperpiano che separa la classe A e la classe B è una linea:

   

E in tre dimensioni, l’iperpiano separatore è un piano:

   

Allo stesso modo, in N dimensioni l’iperpiano separatore sarà uno spazio sottodimensionale di (N-1) dimensioni.

Se osservi attentamente, per l’esempio dello spazio bidimensionale, ognuno dei seguenti è un iperpiano valido che separa le classi A e B:

   

Quindi come decidiamo quale iperpiano è il più ottimale? Entra in gioco il classificatore a margine massimo.

 

Classificatore a margine massimo

 

L’iperpiano ottimale è quello che separa le due classi massimizzando il margine tra di esse. E un classificatore che funziona in questo modo viene chiamato classificatore a margine massimo.

 

 

Margini rigidi e morbidi

 

Abbiamo considerato un esempio super semplificato in cui le classi erano perfettamente separabili e il classificatore a margine massimo era una buona scelta. 

Ma cosa succede se i tuoi punti dati sono distribuiti in questo modo? Le classi sono ancora perfettamente separabili da un iperpiano, e l’iperpiano che massimizza il margine avrà questa forma:

   

Ma vedi il problema di questo approccio? Beh, ottiene comunque la separazione delle classi. Tuttavia, si tratta di un modello ad alta varianza che cerca forse di adattare troppo bene i punti della classe A.

Nota, tuttavia, che il margine non ha alcun punto dati classificato erroneamente. Un tale classificatore viene chiamato classificatore a margine rigido.

Osserva invece questo classificatore. Un tale classificatore si comporterebbe meglio? Si tratta di un modello a varianza notevolmente inferiore che si comporterebbe ragionevolmente bene nella classificazione sia dei punti della classe A che dei punti della classe B. 

  Classificatore lineare a vettori di supporto | Immagine di Autore  

Notate che abbiamo un punto dati classificato erroneamente all’interno del margine. Un classificatore del genere, che consente un numero minimo di classificazioni errate, è chiamato classificatore a margine morbido.

Classificatore a Vettori di Supporto

Il classificatore a margine morbido che abbiamo è un classificatore lineare a vettori di supporto. I punti sono separabili da una linea (o un’equazione lineare). Se hai seguito fin qui, dovrebbe essere chiaro cosa sono i vettori di supporto e perché vengono chiamati così.

Ogni punto dati è un vettore nello spazio delle caratteristiche. I punti dati che sono più vicini all’iperpiano di separazione vengono chiamati vettori di supporto perché supportano o aiutano la classificazione.

È interessante notare che se rimuovi un singolo punto dati o un sottoinsieme di punti dati che non sono vettori di supporto, l’iperpiano di separazione non cambia. Ma se rimuovi uno o più vettori di supporto, l’iperpiano cambia.

Negli esempi fino ad ora, i punti dati erano linearmente separabili. Quindi abbiamo potuto adattare un classificatore a margine morbido con il minimo errore possibile. Ma cosa succede se i punti dati sono distribuiti in questo modo?

Dati Non Linearmente Separabili | Immagine dell’Autore

In questo esempio, i punti dati non sono linearmente separabili. Anche se abbiamo un classificatore a margine morbido che consente classificazioni errate, non saremo in grado di trovare una linea (iperpiano di separazione) che ottenga buone prestazioni su queste due classi.

Cosa facciamo adesso?

Support Vector Machines e il Kernel Trick

Ecco un riassunto di ciò che faremmo:

  • Problema: I punti dati non sono linearmente separabili nello spazio delle caratteristiche originale.
  • Soluzione: Proiettare i punti su uno spazio dimensionale superiore in cui sono linearmente separabili.

Ma proiettare i punti su uno spazio dimensionale superiore richiede di mappare i punti dati dallo spazio delle caratteristiche originale allo spazio dimensionale superiore.

Questa ricomputazione comporta un overhead non trascurabile, specialmente quando lo spazio su cui vogliamo proiettare ha dimensioni molto maggiori dello spazio delle caratteristiche originale. Ecco dove entra in gioco il kernel trick.

Matematicamente, il classificatore a vettori di supporto può essere rappresentato dalla seguente equazione [1]:

Qui, è una costante e indica che facciamo la somma sugli indici corrispondenti ai punti di supporto.

è il prodotto interno tra i punti e . Il prodotto interno tra due vettori a e b è dato da:

La funzione kernel K(.) consente di generalizzare il classificatore a vettori di supporto lineare per i casi non lineari. Sostituiamo il prodotto interno con la funzione kernel:

La funzione kernel tiene conto della non linearità. E consente anche di eseguire calcoli—sui punti dati nello spazio delle caratteristiche originale—senza doverli ricalcolare nello spazio dimensionale superiore.

Per il classificatore lineare di supporto vettoriale, la funzione kernel è semplicemente il prodotto interno e assume la seguente forma:

 

 

Support Vector Machines in Scikit-Learn 

 

Ora che abbiamo compreso l’intuizione dietro le macchine a vettori di supporto, codifichiamo un esempio rapido utilizzando la libreria scikit-learn. 

Il modulo svm nella libreria scikit-learn offre implementazioni di classi come Linear SVC, SVC e NuSVC. Queste classi possono essere utilizzate sia per la classificazione binaria che per la classificazione multiclasse. La documentazione estesa di scikit-learn elenca i kernel supportati. 

Utilizzeremo il dataset integrato wine. Si tratta di un problema di classificazione in cui le caratteristiche del vino vengono utilizzate per prevedere l’etichetta di output che può essere una delle tre classi: 0, 1 o 2. È un dataset di piccole dimensioni con circa 178 record e 13 caratteristiche.

Qui ci concentreremo solo su:

  • caricamento e preelaborazione dei dati e
  • addestramento del classificatore con il dataset 

 

Passaggio 1: Importa le librerie necessarie e carica il dataset

 

Prima di tutto, carichiamo il dataset wine disponibile nel modulo datasets di scikit-learn:

from sklearn.datasets import load_wine

# Carica il dataset wine
wine = load_wine()
X = wine.data
y = wine.target

 

Passaggio 2: Divide il dataset in training e test dataset

 

Dividiamo il dataset in set di addestramento e test. Qui, utilizziamo una divisione 80:20 in cui l’80% e il 20% dei punti dati vanno rispettivamente ai set di addestramento e test:

from sklearn.model_selection import train_test_split

# Dividi il dataset in set di addestramento e test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=10)

 

Passaggio 3: Preelabora il dataset

 

Successivamente, preelaboriamo il dataset. Utilizziamo uno StandardScaler per trasformare i punti dati in modo che seguano una distribuzione con media zero e varianza unitaria:

# Preelaborazione dei dati
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

 

Ricorda di non utilizzare fit_transform sul set di test in quanto ciò potrebbe causare il sottile problema della perdita di dati.

 

Passaggio 4: Istanziare un classificatore SVM e addestrarlo con i dati di addestramento

 

Utilizzeremo SVC per questo esempio. Istanziamo svm, un oggetto SVC, e addestralo con i dati di addestramento:

from sklearn.svm import SVC

# Crea un classificatore SVM
svm = SVC()

# Addestra il classificatore SVM con i dati di addestramento
svm.fit(X_train_scaled, y_train)

 

Passaggio 5: Prevedere le etichette per i campioni di test

 

Per prevedere le etichette di classe per i dati di test, possiamo chiamare il metodo predict sull’oggetto svm:

# Prevedi le etichette per il set di test
y_pred = svm.predict(X_test_scaled)

 

Passaggio 6: Valutare l’accuratezza del modello

 

Per concludere, calcoleremo solo l’accuratezza. Ma possiamo anche ottenere un rapporto di classificazione e una matrice di confusione molto dettagliati. 

from sklearn.metrics import accuracy_score

# Calcola l'accuratezza del modello
accuratezza = accuracy_score(y_test, y_pred)
print(f"{accuratezza=:.2f}")

 

Output >>> accuratezza=0.97

 

Ecco il codice completo:

from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score

# Carica il dataset del vino
vino = load_wine()
X = vino.data
y = vino.target

# Dividi il dataset in set di addestramento e test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=10)

# Preprocessing dei dati
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# Crea un classificatore SVM
svm = SVC()

# Addestra il classificatore SVM ai dati di addestramento
svm.fit(X_train_scaled, y_train)

# Prevedi le etichette per il set di test
y_pred = svm.predict(X_test_scaled)

# Calcola l'accuratezza del modello
accuratezza = accuracy_score(y_test, y_pred)
print(f"{accuratezza=:.2f}")

 

Abbiamo un semplice classificatore a vettori di supporto. Ci sono iperparametri che è possibile regolare per migliorare le prestazioni del classificatore a vettori di supporto. Gli iperparametri comunemente regolati includono la costante di regolarizzazione C e il valore gamma.

 

Conclusioni 

 

Spero che tu abbia trovato utile questa guida introduttiva alle macchine a vettori di supporto. Abbiamo coperto abbastanza intuizione e concetti per comprendere come funzionano le macchine a vettori di supporto. Se sei interessato a approfondire, puoi consultare i riferimenti collegati di seguito. Continua a imparare!

 

Riferimenti e Risorse di Apprendimento

 

[1] Capitolo sulle macchine a vettori di supporto, Introduzione all’Apprendimento Statistico (ISLR)

[2] Capitolo sulle macchine a nucleo, Introduzione all’Apprendimento Automatico

[3] Macchine a vettori di supporto, documentazione di scikit-learn     Bala Priya C è una sviluppatrice e scrittrice tecnica proveniente dall’India. Le piace lavorare all’intersezione tra matematica, programmazione, scienza dei dati e creazione di contenuti. Le sue aree di interesse e competenza includono DevOps, scienza dei dati e elaborazione del linguaggio naturale. Ama leggere, scrivere, programmare e il caffè! Attualmente sta lavorando per imparare e condividere le sue conoscenze con la comunità di sviluppatori scrivendo tutorial, guide pratiche, articoli di opinione e altro ancora.