La tua prima regressione

L

La regressione è uno dei due principali problemi dell’apprendimento supervisionato, la branca del machine learning che vuole insegnare ai computer a risolvere un determinato problema mostrandogli come questo problema è stato già risolto in passato.

Intuitivamente la regressione consente di trovare la relazione tra input e output, in modo da predire output futuri avendo a disposizione solamente l’input.

Ad esempio, avendo a disposizione un set di dati contenente le specifiche di diversi smartphone e il relativo prezzo di listino, potremmo utilizzare la regressione per predire a che prezzo potrà essere venduto un nuovo smartphone basandosi sulle sue specifiche.

Altri esempi molto più comuni sono il provare a predire il valore futuro di un titolo in borsa in base ai valori passati, provare a predire l’affluenza di utenti al blog in base ai contenuti di un articolo che si vuole pubblicare o il numero di nuovi iscritti in base a delle campagne di advertising in pianificazione.

Matematicamente la regressione può essere intesa come il trovare la funzione che meglio approssima la relazione tra la variabile indipendente X (l’input) e la variabile dipendente Y (l’output). Nel caso di una regressione lineare questa funzione è un semplice polinomio.

Graficamente questa relazione lineare può essere rappresentata come una retta che passa il più vicino possibile a tutti i punti costituiti da input X e output Y.

Predire il valore di un’abitazione

Per questo primo esempio utilizzeremo il popolarissimo Boston Housing Dataset, un dataset contenente diverse informazioni riguardo alcune alcune abitazioni nei dintorni di Boston.

Un dataset strutturato si può presentare in diversi formati: CSV, TSV, XML, HTTP, JSON, EXCEL eccetera, in ogni caso questo ha una struttura tabulare.

  • Una delle colonne della tabella è il valore che vogliamo addestrare il nostro modello a predire e prende il nome di target.
  • Tutte le altre colonne sono proprietà che possiamo potenzialmente usare per creare il nostro modello, purché abbiano una relazione con il target, e vengono chiamate features.

Pandas è una libreria Python sviluppata appositamente per chi lavora con i dati e mette a disposizione una particolare struttura dati chiamata DataFrame che si presta particolarmente bene a contenere dati in forma tabulare.

Carichiamo il Boston Housing Dataset all’interno di un DataFrame utilizzando la funzione read_csv, seguita dal metodo head del DataFrame per vedere le sue prime 5 righe.

import pandas as pd

boston = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/housing/housing.data",
sep='\s+', #le colonne all'interno del file sono separate da un numero variabile di spazi, in questo caso dobbiamo utilizzare l'espressione regolare '\s+'
names=["CRIM","ZN","INDUS","CHAS","NOX","RM","AGE","DIS","RAD","TAX","PRATIO","B","LSTAT","MEDV"]) # impostiamo dei nomi per le colonne

boston.head() # passando un valore n a questo metodo stamperemo i primi n esempi del dataset

Il DataFrame avrà questa struttura:

La colonna che abbiamo denominato MEDV contiene il valore dell’abitazione in 1000 dollari (ad esempio un MEDV di 24 corrisponde a 24.000 dollari) ed è il nostro target.

 

Regressione lineare semplice

Una regressione lineare semplice utilizza un’unica feature per costruire il modello, nel nostro caso utilizzeremo solo il numero di stanze, cioè la colonna che abbiamo denominato RM.

Estraiamo la feature RM e il target MEDV e salviamo i valori all’interno di due array numpy che ci serviranno per l’addestramento.

X = boston[['RM']].values # con l'attributo values ottieniamo l'array
Y = boston["MEDV"].values

E’ buona pratica nel machine learning eseguire l’addestramento su un set di dati per poi verificare i risultati delle sue predizioni con un altro set contente dati non visti durante l’addestramento.
Questo garantisce che il nostro modello è in grado di generalizzare su dati sconosciuti e quindi ha realmente “imparato” dai dati, piuttosto che limitarsi a memorizzare il set di addestramento, condizione conosciuta come overfitting.

Per fare questo dobbiamo suddividere il nostro dataset in due set distinti, uno da utilizzare unicamente per l’addestramento e un altro da utilizzare per il test, possiamo farlo utilizzando il metodo train_test_split di scikit-learn.

from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X,Y, test_size=0.3, random_state=0)

Adesso abbiamo tutto ciò che ci serve per costruire il modello, facciamolo utilizzando la classe LinearRegression di scikit-learn:

  • con il metodo fit eseguiamo l’addestramento
  • con il metodo predict eseguiamo la predizione

Queste due semplici API sono comuni tra tutti i modelli definiti in scikit-learn, il ché rende il sostituire un modello con un altro estremamente semplice.

from sklearn.linear_model import LinearRegression

ll = LinearRegression()
ll.fit(X_train, Y_train) # passiamo i set di addestramento 
Y_pred_train = ll.predict(X_train) # eseguiamo la predizione sul train set
Y_pred_test = ll.predict(X_test) # eseguiamo la predizione anche sul test set

Congratulazioni ! Hai costruito il tuo primo modello di regressione e hai eseguito la tua prima predizione. Adesso bisogna vedere quanto buono è questo modello.
Per farlo dobbiamo definire una metrica che ci permetterà di misurare quanto le predizioni del modello si avvicinano ai valori corretti.
Una metrica semplice che fa proprio questo è l’errore quadratico medio (mean squadred error – MSE)

from sklearn.metrics import mean_squared_error

print("MSE train: %f" % mean_squared_error(Y_train, Y_pred_train))
print("MSE test: %f" % mean_squared_error(Y_test, Y_pred_test))

Il risultato dovrebbe essere circa 42.16 per il train set e 47.03 per il test set, come vanno interpretati ?

Estraendo la radice quadrata otteniamo un valore che indica mediamente di quanto si è sbagliato il modello. Nel nostro caso, il test set ha ottenuto un MSE di 47 la cui radice quadrata è circa 6.9, considerando che i prezzi delle case sono rappresentati in 1000 dollari questo ci dice che in media il modello ha fatto cilecca per 6900 dollari.

Una metrica più intuitiva è il coefficiente di indeterminazione (anche conosciuto come R-squared score), può essere inteso come una versione standardizzata del MSE e ritorna un punteggio compreso tra 0 e 1 che può essere letto in questo modo:

  • R2_score < 0.3 il modello è inutile.
  • 0.3 < R2_score < 0.5 il modello è scarso.
  • 0.5 < R2_score < 0.7 il modello è discreto.
  • 0.7 < R2_score < 0.9 il modello è buono.
  • 0.9 < R2_score < 1 il modello è ottimo.
  • R2_score = 1 molto probabilmente c’è un errore nel modello.
from sklearn.metrics import r2_score

print("R2 train: %f" % r2_score(Y_train, Y_pred_train))
print("R2 test: %f" % r2_score(Y_test, Y_pred_test))

Se hai fatto tutto correttamente dovresti ottenere un punteggio R-squared di circa 0.50 sul train set e 0.435 sul test set.

Il risultato non è così male considerando le poche informazioni che abbiamo utilizzato (solamente il numero di stanze), ma possiamo fare meglio !

Regressione lineare multipla

Una regressione lineare multipla è un modello che utilizza due o più features per l’addestramento.

Proviamo a predire il valore delle abitazioni utilizzando tutte le 13 features presenti nel nostro dataset, ricreiamo i nostri array con features e target, questa volta selezionando tutte le proprietà.

X = boston.drop("MEDV", axis=1).values # utilizzando drop rimuoviamo la colonna del prezzo e selezioniamo tutte le altre
Y = boston["MEDV"].values

X_train, X_test, Y_train, Y_test = train_test_split(X,Y, test_size=0.3, random_state=0)

Quando lavoriamo con più features dobbiamo essere sicuri che queste siano comprese in un range di valori comune, per far questo abbiamo due possibilità:

  • Normalizzazione: portiamo tutti i dati in un range compreso tra 0 e 1
  • Standardizzazione: convertiamo i dati in una distribuzione normale con media 0 e deviazione standard 1.

Standardizziamo l’array con le features utilizzando la classe StandardScaler di scikit-learn

from sklearn.preprocessing import StandardScaler

ss = StandardScaler()
X_train_std = ss.fit_transform(X_train)
X_test_std = ss.transform(X_test)

Adesso possiamo creare il modello esattamente come fatto prima…

from sklearn.linear_model import LinearRegression

ll = LinearRegression()
ll.fit(X_train_std, Y_train)
Y_pred_train = ll.predict(X_train_std)
Y_pred_test = ll.predict(X_test_std)

… e calcolare le metriche

print("MSE train: %f" % mean_squared_error(Y_train, Y_pred_train))
print("MSE test: %f" % mean_squared_error(Y_test, Y_pred_test))

print("R2 train: %f" % r2_score(Y_train, Y_pred_train))
print("R2 test: %f" % r2_score(Y_test, Y_pred_test))

Dovresti ottenere i seguenti risultati:

  • MSE del train set ≈ 19.96
  • MSE del test set ≈ 27.16
  • R2 del train set ≈ 0.76
  • R2 del test set ≈ 0.67

Come vedi il risultato è nettamente superiore rispetto a quanto ottenuto con un’unica feature, avendo più informazioni a disposizione l’algoritmo di machine learning è riuscito a individuare pattern migliori e quindi a eseguire predizioni migliori.

Infatti una cosa da tenere sempre a mente è che, spesso, nel machine learning la quantità ma soprattutto la qualità dei dati riveste un ruolo anche superiore a quello degli algoritmi stessi.

Trovi questo articolo in versione notebook eseguibile sulla repository Github dei tutorial di ProfessionAI.


Questo articolo è stato originariamente pubblicato sul blog di ProfessionAI, la prima piattaforma italiana per la formazione online nelle varie discipline legate all’Intelligenza Artificiale, come machine learning, deep learning e data science.

A proposito di me

Giuseppe Gullo

Programmatore, imprenditore e investitore, ho cominciato a programmare a 13 anni e appena maggiorenne mi sono avvicinato all'intelligenza artificiale. Ho creato diverse dozzine di servizi web e mobile raggiungendo centinaia di migliaia di persone in tutto il mondo.
Il mio life goal è utilizzare le potenzialità dell'intelligenza artificiale per migliorare la condizione di vita delle persone.

I nostri Partner

Gli articoli più letti

Articoli recenti

Commenti recenti