Come utilizzare la regressione della rete elastica |  di Chris Taylor |  Marzo 2024

 | Intelligenza-Artificiale

Lancia una rete flessibile che trattiene solo i pesci di grandi dimensioni

Nota: il codice utilizzato in questo articolo utilizza tre script personalizzati, data_cleaning, data_reviewE , edaa cui è possibile accedere tramite un pubblico Repositorio GitHub.

fotografato da Eric BARBEAU SU Unsplash

È come una rete da pesca estensibile che trattiene “tutti i pesci grossi” Zou & Hastie (2005) p. 302

La regressione lineare è uno strumento didattico comunemente utilizzato nella scienza dei dati e, nelle condizioni appropriate (ad esempio, relazione lineare tra variabili indipendenti e dipendenti, assenza di multicollinearità), può essere un metodo efficace per prevedere una risposta. Tuttavia, in alcuni scenari (ad esempio, quando la struttura del modello diventa complessa), il suo utilizzo può essere problematico.

Per affrontare alcuni dei limiti dell'algoritmo, sono state suggerite tecniche di penalizzazione o regolarizzazione (1). Due metodi popolari di regolarizzazione sono la regressione ridge e lazo, ma scegliere tra questi metodi può essere difficile per chi è nuovo nel campo della scienza dei dati.

Un approccio alla scelta tra regressione ridge e lazo consiste nell'esaminare la rilevanza delle caratteristiche rispetto alla variabile di risposta (2). Quando la maggior parte delle caratteristiche del modello sono rilevanti (cioè contribuiscono al potere predittivo del modello), la penalità di regressione ridge (o penalità L2) dovrebbe essere aggiunta alla regressione lineare.

Quando viene aggiunta la penalità di regressione della cresta, la funzione di costo del modello è:

Immagine dell'autore
  • θ = il vettore dei parametri o coefficienti del modello
  • α = forza complessiva della regolarizzazione
  • M = il numero di esempi di formazione
  • N = il numero di caratteristiche nel set di dati

Quando la maggior parte delle caratteristiche sono irrilevanti (cioè non contribuiscono al potere predittivo del modello), la penalità di regressione lazo (o penalità L1) dovrebbe essere aggiunta alla regressione lineare.

Quando viene aggiunta la penalità di regressione al lazo, la funzione di costo del modello è:

Immagine dell'autore

La pertinenza può essere determinata tramite revisione manuale o convalida incrociata; tuttavia, quando si lavora con diverse funzionalità, il processo diventa dispendioso in termini di tempo e di calcolo.

Una soluzione efficiente e flessibile a questo problema è l’utilizzo della regressione della rete elastica, che combina le penalità della cresta e del lazo.

La funzione di costo per la regressione della rete elastica è:

Immagine dell'autore
  • r = il rapporto di miscelazione tra la regressione della cresta e quella del lazo.

Quando r è 1, viene utilizzata solo la penalità del lazo e quando r è 0, viene utilizzata solo la penalità della cresta. Quando r è un valore compreso tra 0 e 1, viene utilizzata una combinazione di penalità.

Oltre ad essere adatta per set di dati con diverse funzionalità, la regressione della rete elastica ha altri attributi che la rendono uno strumento interessante per i data scientist (1):

  • Selezione automatica delle caratteristiche rilevanti, che si traduce in modelli parsimoniosi e facili da interpretare
  • Ritiro continuo, che riduce gradualmente i coefficienti delle caratteristiche meno rilevanti verso lo zero (opposto ad una riduzione immediata a zero)
  • Possibilità di selezionare gruppi di caratteristiche correlate, invece di selezionare arbitrariamente una caratteristica dal gruppo

Grazie alla sua utilità e flessibilità, Zou e Hastie (2005) hanno paragonato il modello a una “…rete da pesca estensibile che trattiene tutti i pesci di grandi dimensioni”. (p. 302), dove i grandi pesci sono analoghi a caratteristiche rilevanti.

Ora che abbiamo alcune informazioni di base, possiamo procedere con l'implementazione della regressione della rete elastica su un set di dati reale.

Una grande risorsa per i dati è il Machine Learning Repository (UCI ML Repo) dell'Università della California a Irvine. Per il tutorial utilizzeremo il Wine Quality Dataset (3), concesso in licenza con a Creative Commons Attribuzione 4.0 Internazionale licenza.

La funzione visualizzata di seguito può essere utilizzata per ottenere set di dati e informazioni sulle variabili dall'UCI ML Repo inserendo il numero identificativo come parametro della funzione.

pip install ucimlrepo # unless already installed
from ucimlrepo import fetch_ucirepo
import pandas as pd

def fetch_uci_data(id):
"""
Function to return features datasets from the UCI ML Repository.

Parameters
----------
id: int
Identifying number for the dataset

Returns
----------
df: df
Dataframe with features and response variable
"""
dataset = fetch_ucirepo(id=id)

features = pd.DataFrame(dataset.data.features)
response = pd.DataFrame(dataset.data.targets)
df = pd.concat((features, response), axis=1)

# Print variable information
print('Variable Information')
print('--------------------')
print(dataset.variables)

return(df)

# Wine Quality's identification number is 186
df = fetch_uci_data(186)

Un dataframe panda è stato assegnato alla variabile “df” e le informazioni sul set di dati sono state stampate.

Analisi esplorativa dei dati

Variable Information
--------------------
name role type demographic \
0 fixed_acidity Feature Continuous None
1 volatile_acidity Feature Continuous None
2 citric_acid Feature Continuous None
3 residual_sugar Feature Continuous None
4 chlorides Feature Continuous None
5 free_sulfur_dioxide Feature Continuous None
6 total_sulfur_dioxide Feature Continuous None
7 density Feature Continuous None
8 pH Feature Continuous None
9 sulphates Feature Continuous None
10 alcohol Feature Continuous None
11 quality Target Integer None
12 color Other Categorical None

description units missing_values
0 None None no
1 None None no
2 None None no
3 None None no
4 None None no
5 None None no
6 None None no
7 None None no
8 None None no
9 None None no
10 None None no
11 score between 0 and 10 None no
12 red or white None no

In base alle informazioni sulle variabili, possiamo vedere che ci sono 11 “caratteristiche”, 1 “target” e 1 “altro” variabili nel set di dati. Questa è un'informazione interessante: se avessimo estratto i dati senza le informazioni variabili, forse non avremmo saputo che erano disponibili dati sulla famiglia (o colore) del vino. Al momento non incorporeremo la variabile “colore” nel modello, ma è bello sapere che è disponibile per le future iterazioni del progetto.

La colonna “descrizione” nelle informazioni sulla variabile suggerisce che la variabile “qualità” è categorica. I dati sono probabilmente ordinali, nel senso che hanno una struttura gerarchica, ma non è garantito che gli intervalli tra i dati siano uguali o noti. In termini pratici, significa che un vino valutato come 4 non è due volte migliore di un vino valutato come 2. Per risolvere questo problema, convertiremo i dati nel tipo di dati corretto.

df('quality') = df('quality').astype('category')

Per comprendere meglio i dati, possiamo utilizzare il file countplot() metodo da seaborn pacchetto per visualizzare la distribuzione della variabile “qualità”.

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style='whitegrid') # optional

sns.countplot(data=df, x='quality')
plt.title('Distribution of Wine Quality')
plt.xlabel('Quality')
plt.ylabel('Count')
plt.show()

Immagine dell'autore

Quando si esegue un'analisi esplorativa dei dati, è utile creare istogrammi per caratteristiche numeriche. Inoltre, raggruppare le variabili in base a una variabile categoriale può fornire nuove informazioni. L'opzione migliore per raggruppare i dati è “qualità”. Tuttavia, dato che ci sono 7 gruppi di qualità, le trame potrebbero diventare difficili da leggere. Per semplificare il raggruppamento, possiamo creare una nuova funzionalità, “rating”, che organizza i dati sulla “qualità” in tre categorie: bassa, media e alta.

def categorize_quality(value):
if 0 <= value <= 3:
return 0 # low rating
elif 4 <= value <= 6:
return 1 # medium rating
else:
return # high rating

# Create new column for 'rating' data
df('rating') = df('quality').apply(categorize_quality)

Per determinare quanti vini sono presenti in ciascun gruppo, possiamo utilizzare il seguente codice:

df('rating').value_counts()
rating
1 5190
2 1277
0 30
Name: count, dtype: int64

In base all'output del codice, possiamo vedere che la maggior parte dei vini sono classificati come “medi”.

Ora possiamo tracciare gli istogrammi dei gruppi di caratteristiche numeriche per “valutazione”. Per tracciare l'istogramma dovremo usare il file gen_histograms_by_category() metodo da eda script nel repository GitHub condiviso all'inizio dell'articolo.

import eda 

eda.gen_histograms_by_category(df, 'rating')

Immagine dell'autore

Sopra è riportato uno dei grafici generati dal metodo. Una revisione del grafico indica che c'è una certa distorsione nei dati. Per ottenere una misura più precisa dell'inclinazione, insieme ad altre statistiche, possiamo utilizzare get_statistics() metodo da data_review sceneggiatura.

from data_review import get_statistics

get_statistics(df)

-------------------------
Descriptive Statistics
-------------------------
fixed_acidity volatile_acidity citric_acid residual_sugar chlorides free_sulfur_dioxide total_sulfur_dioxide density pH sulphates alcohol quality
count 6497.000000 6497.000000 6497.000000 6497.000000 6497.000000 6497.000000 6497.000000 6497.000000 6497.000000 6497.000000 6497.000000 6497.000000
mean 7.215307 0.339666 0.318633 5.443235 0.056034 30.525319 115.744574 0.994697 3.218501 0.531268 10.491801 5.818378
std 1.296434 0.164636 0.145318 4.757804 0.035034 17.749400 56.521855 0.002999 0.160787 0.148806 1.192712 0.873255
min 3.800000 0.080000 0.000000 0.600000 0.009000 1.000000 6.000000 0.987110 2.720000 0.220000 8.000000 3.000000
25% 6.400000 0.230000 0.250000 1.800000 0.038000 17.000000 77.000000 0.992340 3.110000 0.430000 9.500000 5.000000
50% 7.000000 0.290000 0.310000 3.000000 0.047000 29.000000 118.000000 0.994890 3.210000 0.510000 10.300000 6.000000
75% 7.700000 0.400000 0.390000 8.100000 0.065000 41.000000 156.000000 0.996990 3.320000 0.600000 11.300000 6.000000
max 15.900000 1.580000 1.660000 65.800000 0.611000 289.000000 440.000000 1.038980 4.010000 2.000000 14.900000 9.000000
skew 1.723290 1.495097 0.471731 1.435404 5.399828 1.220066 -0.001177 0.503602 0.386839 1.797270 0.565718 0.189623
kurtosis 5.061161 2.825372 2.397239 4.359272 50.898051 7.906238 -0.371664 6.606067 0.367657 8.653699 -0.531687 0.23232

Coerentemente con l'istogramma, la caratteristica etichettata “fixed_acidity” ha un'asimmetria di 1,72 che indica una significativa asimmetria a destra.

Per determinare se esistono correlazioni tra le variabili, possiamo utilizzare un'altra funzione da eda sceneggiatura.

eda.gen_corr_matrix_hmap(df)
Immagine dell'autore

Sebbene esistano alcune relazioni moderate e forti tra le caratteristiche, la regressione della rete elastica funziona bene con variabili correlate, pertanto non è richiesta alcuna azione (2).

Pulizia dei dati

Affinché l'algoritmo di regressione della rete elastica venga eseguito correttamente, i dati numerici devono essere scalati e le variabili categoriali devono essere codificate.

Per pulire i dati, eseguiremo i seguenti passaggi:

  1. Ridimensionare i dati utilizzando il scale_data() metodo dal data_cleaning sceneggiatura
  2. Codificare le variabili “qualità” e “rating” utilizzando il file get_dummies() metodo da pandas
  3. Separare le caratteristiche (ad esempio X) e la variabile di risposta (ad esempio y) utilizzando il simbolo separate_data() metodo
  4. Dividere i dati in set di training e test utilizzando train_test_split()
from sklearn.model_selection import train_test_split
from data_cleaning import scale_data, separate_data

df_scaled = scale_data(df)
df_encoded = pd.get_dummies(df_scaled, columns=('quality', 'rating'))

# Separate features and response variable (i.e., 'alcohol')
X, y = separate_data(df_encoded, 'alcohol')

# Create test and train sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size =0.2, random_state=0)

Costruzione e valutazione del modello

Per addestrare il modello, utilizzeremo ElasticNetCV() che ha due parametri, alpha E l1_ratioe convalida incrociata integrata. IL alpha Il parametro determina la forza della regolarizzazione applicata al modello e l1_ratio determina il mix tra penalità lazo e cresta (equivale alla variabile R che è stato rivisto nel Sfondo sezione).

  • Quando l1_ratio è impostato su un valore pari a 0, viene utilizzata la penalità di regressione della cresta.
  • Quando l1_ratio è impostato su un valore pari a 1, viene utilizzata la penalità di regressione lazo.
  • Quando l1_ratio è impostato su un valore compreso tra 0 e 1, viene utilizzata una combinazione di entrambe le penalità.

Scegliere i valori per alpha E l1_ratio può essere impegnativo; tuttavia, l'attività è resa più semplice dall'uso della convalida incrociata, integrata ElasticNetCV(). Per semplificare il processo, non è necessario fornire un elenco di valori da alpha E l1_ratio – puoi lasciare che il metodo faccia il lavoro pesante.

from sklearn.linear_model import ElasticNet, ElasticNetCV

# Build the model
elastic_net_cv = ElasticNetCV(cv=5, random_state=1)

# Train the model
elastic_net_cv.fit(X_train, y_train)

print(f'Best Alpha: {elastic_net_cv.alpha_}')
print(f'Best L1 Ratio:{elastic_net_cv.l1_ratio_}')

Best Alpha: 0.0013637974514517563
Best L1 Ratio:0.5

Sulla base della stampa, possiamo vedere i valori migliori per alpha E l1_ratio sono 0,001 e 0,5, rispettivamente.

Per determinare il rendimento del modello, possiamo calcolare l'errore quadratico medio e il punteggio R quadrato del modello.

from sklearn.metrics import mean_squared_error

# Predict values from the test dataset
elastic_net_pred = elastic_net_cv.predict(X_test)

mse = mean_squared_error(y_test, elastic_net_pred)
r_squared = elastic_net_cv.score(X_test, y_test)

print(f'Mean Squared Error: {mse}')
print(f'R-squared value: {r_squared}')

Mean Squared Error: 0.2999434011721803
R-squared value: 0.7142939720612289

Conclusione

Sulla base delle metriche di valutazione, il modello funziona moderatamente bene. Tuttavia, le sue prestazioni potrebbero essere migliorate attraverso alcuni passaggi aggiuntivi, come il rilevamento e la rimozione di valori anomali, la progettazione di funzionalità aggiuntive e la fornitura di un insieme specifico di valori per alpha E l1_ratio In ElasticNetCV(). Sfortunatamente, questi passaggi vanno oltre lo scopo di questo semplice tutorial; tuttavia, potrebbero fornire alcune idee su come questo progetto potrebbe essere migliorato da altri.

Grazie per aver dedicato del tempo a leggere questo articolo. Se hai domande o feedback, lascia un commento.

(1) H. Zou e T. Hastie, Regolarizzazione e selezione delle variabili tramite la rete elastica, Journal of the Royal Statistical Society Series B: Statistical Methodology, volume 67, numero 2, aprile 2005, pagine 301–320, https://doi.org/10.1111/j.1467-9868.2005.00503.x

(2) A. Géron, Apprendimento automatico pratico con Scikit-Learn, Keras e Tensorflow: concetti, strumenti e tecniche per costruire sistemi intelligenti (2021), O'Reilly.

(3) P. Cortez, A. Cerdeira, F. Almeida, T. Matos e Reis, J.. (2009). Qualità del vino. Repository per l'apprendimento automatico dell'UCI. https://doi.org/10.24432/C56S3T.

Fonte: towardsdatascience.com

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *