Support Vector Regression (SVR) nel Machine Learning con scikit-learn

Support Vector Regression header

La Support Vector Regression (SVR) è una tecnica di regressione che si basa sul concetto di Support Vector Machines (SVM) e mira a trovare una funzione che approssimi i dati di addestramento minimizzando l’errore, ma consentendo anche una certa quantità di errore entro un margine specificato.

La Support Vector Regression

La Support Vector Regression (SVR) è una tecnica derivata dalle Support Vector Machines (SVM), che originariamente sono state sviluppate per problemi di classificazione binaria. Le SVM sono state introdotte da Vladimir Vapnik e Alexey Chervonenkis negli anni ’60 e ’70. Successivamente, l’idea è stata estesa alla regressione, portando alla creazione della SVR. Il passaggio da SVM a SVR coinvolge l’estensione del concetto di Support Vector Machines per gestire problemi di regressione. Nella SVM, l’obiettivo è trovare un iperpiano che massimizzi il margine tra le classi, mentre nella SVR, l’obiettivo è trovare una funzione che approssimi i dati di addestramento entro un certo margine di tolleranza.

La SVR coinvolge la minimizzazione di una funzione di costo che tiene conto sia dell’errore di previsione che della complessità del modello. La funzione obiettivo può essere rappresentata come:

 \min_{w, b, \zeta, \zeta^<em>} \frac{1}{2} \lVert w \rVert^2 + C \sum_{i=1}^{N} (\zeta_i + \zeta_i^</em>)

Sotto i vincoli:

 y_i - w^T \phi(x_i) - b \leq \varepsilon + \zeta_i
 w^T \phi(x_i) + b - y_i \leq \varepsilon + \zeta_i^*
 \zeta_i, \zeta_i^* \geq 0 è

Dove:

  •  w è il vettore dei pesi.
  •  b è il termine bias.
  •  \phi(x) è la funzione di mappatura nello spazio delle caratteristiche.
  •  \varepsilon è il margine di tolleranza.
  •  \zeta_i e  \zeta_i^* sono variabili di slack che misurano l’errore di previsione.
  •  C è un parametro di regolarizzazione che controlla il trade-off tra la complessità del modello e la penalizzazione per gli errori.

Aggiungiamo alcune considerazioni da fare:

  • Kernel Trick: SVR può beneficiare del “kernel trick” per gestire relazioni non lineari, mappando i dati in uno spazio delle caratteristiche più complesso.
  • Tuning dei Parametri: La scelta del kernel e dei parametri come ( C ), ( \varepsilon ), e ( \gamma ) (nel caso di kernel RBF) richiede attenzione per ottenere buone prestazioni del modello.
  • Robustezza: SVR è robusta rispetto ai valori anomali nei dati di addestramento grazie alla presenza delle variabili di slack.
  • Interpretazione: La interpretabilità del modello può essere un aspetto sfidante, specialmente quando si utilizzano kernel complessi.

In sintesi, SVR è una tecnica utile per la regressione che sfrutta i principi delle Support Vector Machines, cercando di trovare una funzione che approssimi i dati di addestramento entro un margine specificato, permettendo al contempo un certo grado di errore.

Python Data Analytics

Se vuoi approfondire l’argomento e scoprire di più sul mondo della Data Science con Python, ti consiglio di leggere il mio libro:

Python Data Analytics 3rd Ed

Fabio Nelli

Esempio di un problema di regressione con Support Vector Regression e scikit-learn

Support Vector Regression (SVR) è incluso nella libreria scikit-learn, che è una delle librerie più utilizzate per il machine learning in Python. Scikit-learn fornisce un’implementazione efficiente e semplice da utilizzare di Support Vector Regression insieme ad altre tecniche di machine learning. Puoi utilizzare la classe SVR di scikit-learn per creare, addestrare e utilizzare modelli di regressione basati su support vector machines (SVM). Ecco un esempio di utilizzo di SVR in Python utilizzando scikit-learn:

from sklearn.svm import SVR
import numpy as np
import matplotlib.pyplot as plt

# Generiamo dati di esempio
X = np.sort(5 * np.random.rand(80, 1), axis=0)
y = np.sin(X).ravel()

# Aggiungiamo rumore ai dati
y[::5] += 3 * (0.5 - np.random.rand(16))

# Addestriamo il modello SVR
svr_rbf = SVR(kernel='rbf', C=100, gamma=0.1, epsilon=0.1)
svr_rbf.fit(X, y)

# Prevediamo sui dati di addestramento
y_pred = svr_rbf.predict(X)

# Visualizziamo i risultati
plt.scatter(X, y, color='darkorange', label='data')
plt.plot(X, y_pred, color='navy', lw=2, label='SVR (RBF kernel)')
plt.xlabel('data')
plt.ylabel('target')
plt.title('Support Vector Regression')
plt.legend()
plt.show()

In questo esempio, la SVR con kernel radiale (RBF) viene utilizzata per approssimare una funzione sinusoidale con dati rumorosi. Per prima cosa si effettua la generazione di dati di esempio. Vengono generati dati di esempio X e y rappresentanti una funzione sinusoidale con rumore aggiunto. Si passa poi alla creazione e all’addestramento del modello SVR.

   svr_rbf = SVR(kernel='rbf', C=100, gamma=0.1, epsilon=0.1)
   svr_rbf.fit(X, y)

Viene creato un modello di Support Vector Regression (SVR) con kernel radiale (RBF) e addestrato utilizzando i dati di addestramento. A questo punto, si effettuano le previsioni e la visualizzazione dei risultati tramite la libreria Matplotlib. L’obiettivo è mostrare come il modello approssima i dati di input, includendo il rumore presente nei dati di addestramento.

Eseguendo il codice sopra si ottiene il seguente grafico.

Problema di Regressione: prevedere il prezzo delle case con Support Vector Regression e scikit-learn

Passiamo ora ad un problema di regressione su di un dataset reale, cioè con valori presi da un contesto reale. Esistono a tal proposito dei dataset già pronti e forniti direttamente da scikit-learn specifici per questi scopi di test e studio dei modelli. Possiamo utilizzare Support Vector Regression (SVR) per un problema di regressione utilizzando il dataset fetch_california_housing fornito da scikit-learn. Il dataset contiene dati sul prezzo medio delle case in diverse regioni della California, insieme a varie caratteristiche delle case stesse. Questo dataset è comunemente utilizzato per scopi di regressione.

import pandas as pd
import numpy as np
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVR
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt

housing = fetch_california_housing()

data = pd.DataFrame(data=np.c_[housing['data'], housing['target']], columns=housing['feature_names'] + ['target'])

data.head(10)

Vediamo insieme che tipologia di dati contiene questo dataset:

SVR - dataset fetching california housing

Il dataset fetch_california_housing è un dataset ampiamente utilizzato nel campo del machine learning e della statistica per scopi di regressione. Contiene dati relativi al prezzo medio delle abitazioni in varie regioni della California, insieme a diverse caratteristiche che descrivono le abitazioni stesse. Ecco una descrizione delle principali caratteristiche del dataset:

  • MedInc: Mediana del reddito del blocco.
  • HouseAge: Mediana dell’età delle case nel blocco.
  • AveRooms: Media delle stanze per abitazione nel blocco.
  • AveBedrms: Media delle camere da letto per abitazione nel blocco.
  • Population: Popolazione del blocco.
  • AveOccup: Media dell’occupazione per abitazione.
  • Latitude: Latitudine del centro del blocco.
  • Longitude: Longitudine del centro del blocco.

Il target di regressione è MedHouseVal che è la mediana del valore delle abitazioni per i blocchi della zona in migliaia di dollari.

In sostanza, ogni riga del dataset rappresenta un blocco (quartiere o zona) della California, e ogni colonna rappresenta una caratteristica di quel blocco.

Questo dataset è spesso utilizzato per scopi di regressione per predire il prezzo medio delle abitazioni in base alle caratteristiche del blocco, rendendolo un buon punto di partenza per esperimenti di machine learning nel contesto della regressione.

Vediamo adesso di applicare SVR per la regressione e ottenere così un modello in grado di prevedere il prezzo medio delle abitazioni.

# Split data into training set and test set
X_train, X_test, y_train, y_test = train_test_split(data.drop('target', axis=1), data['target'], test_size=0.2, random_state=42)

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

# Create the SVR model
svr = SVR(kernel='rbf', C=10, gamma='auto')

# Train the model
svr.fit(X_train_scaled, y_train)

# Make predictions
y_pred = svr.predict(X_test_scaled)

# Calculate the mean square error
mse = mean_squared_error(y_test, y_pred)
print("Mean Squared Error:", mse)

Analizzando il codice, dove aver suddiviso il dataset in training set e testing set, si passa alla standardizzazione delle features utilizzando StandardScaler. La standardizzazione è una pratica comune nel machine learning per rendere le features comparabili, riducendo la scala dei valori delle features. Poi si crea un modello SVR utilizzando il kernel radiale (RBF). C e gamma sono parametri del modello che possono essere regolati per ottimizzare le prestazioni del modello. In questo caso, C è impostato su 10 e gamma è impostato su ‘auto’.

Eseguendo si ottiene il seguente valore:

Mean Squared Error: 0.3236927921625923

Che è un discreto risultato. Se vogliamo vedere graficamente la capacità di previsione del modello rispetto al dataset possiamo aggiungere il seguente codice.

plt.scatter(y_test, y_pred)
plt.plot([0, max(y_test)], [0, max(y_test)], color='red', linestyle='--')  # Aggiungi la linea x = y
plt.xlabel("Actual")
plt.ylabel("Predicted")
plt.title("Actual vs Predicted Prices")
plt.show()
SVR - regression accuracy

Come possiamo vedere dal grafico, esiste tutta una serie di elementi del dataset che hanno un valore di target maggiore di 5 (in realtà hanno tutti valore 5.0001) dato che sembrerebbe una valutazione di “fuori scala” e quindi sarebbe meglio eliminarli dal dataset di partenza. Aggiungiamo e modifichiamo il codice precedente per tener conto di questo fatto.

# Remove all rows where the 'target' column value is greater than 5
data_cleaned = data.loc[data['target'] <= 5]

# Split data into training set and test set
X_train, X_test, y_train, y_test = train_test_split(data_cleaned.drop('target', axis=1), data_cleaned['target'], test_size=0.2, random_state=42)

Eseguendo questa volta il codice con il dataset ripulito dai fuori scala otteniamo i seguenti risultati:

Mean Squared Error: 0.2733577250854457
SVR - regression accuracy 2

Come possiamo vedere l’errore quadratico medio si è ridotto, e quindi siamo andati verso la direzione giusta.

Quando usare SVR nei problemi di regressione?

La scelta del modello dipende da diversi fattori, tra cui la natura dei dati, la dimensionalità del dataset, la distribuzione dei dati, la presenza di relazioni lineari o non lineari tra le features e il target, e le prestazioni desiderate. Ecco alcune situazioni in cui l’uso di Support Vector Regression (SVR) potrebbe essere preferibile rispetto ad altri modelli forniti da scikit-learn:

  • Dati non lineari: SVR può gestire efficacemente dati non lineari grazie all’uso di kernel non lineari come il kernel RBF. Se i dati hanno una struttura non lineare complessa, SVR potrebbe essere una scelta appropriata.
  • Robustezza ai dati rumorosi: Gli SVM sono noti per la loro robustezza ai dati rumorosi. Se il tuo dataset contiene molti outlier o dati rumorosi, SVR potrebbe essere una scelta migliore rispetto a modelli sensibili ai dati rumorosi come la regressione lineare.
  • Alta dimensionalità: SVR può gestire efficacemente dataset con un gran numero di features, soprattutto se è presente una bassa frazione di feature rilevanti (sparse data). Inoltre, grazie alla tecnica di regolarizzazione incorporata, SVR può aiutare a evitare l’overfitting anche in presenza di molte features.
  • Scarse conoscenze a priori sulla distribuzione dei dati: Se non si ha una conoscenza a priori chiara sulla distribuzione dei dati o sulla relazione tra le features e il target, SVR può essere una scelta ragionevole in quanto non richiede ipotesi specifiche sulla distribuzione dei dati.
  • Flessibilità nel tuning: SVR offre diversi parametri che possono essere regolati per ottimizzare le prestazioni del modello, come il tipo di kernel, il parametro di regolarizzazione C e i parametri specifici del kernel. Questa flessibilità può essere utile per adattare il modello alle esigenze specifiche del problema.

Tuttavia, è importante notare che SVR potrebbe non essere sempre la scelta migliore. Ad esempio, se il problema di regressione è lineare e non ci sono evidenze di relazioni non lineari tra le features e il target, modelli più semplici come la regressione lineare potrebbero essere più appropriati e computazionalmente meno costosi. Pertanto, è sempre consigliabile esaminare attentamente i dati e sperimentare con diversi modelli per determinare quale funziona meglio per il tuo specifico problema di regressione.

Lascia un commento