Prerequisiti :
Se non sai perchè utilizzeremo python, clicca qui
Se non hai ancora installato Python, clicca qui
Se non sai come scaricare e gestire le librerie, clicca qui
Se non sai cosa sia un Dataset, clicca qui
Introduzione
Personalmente penso che i progetti sono il modo migliore per approfondire la conoscenza della scienza dei dati e delle applicazioni dell'intelligenza artificiale. Infatti, non solo i neofiti, ma anche i professionisti esperti di livello medio possono aggiornare il proprio curriculum con nuovi progetti interessanti. Dopotutto, non sono facili. Ci vuole molto tempo per creare un progetto che possa davvero mostrare la profondità e l'ampiezza delle tue conoscenze.
Spero che questo progetto ti aiuti ad acquisire le conoscenze necessarie e che il tuo curriculum venga inserito più rapidamente nella rosa dei candidati. Questo progetto mostra tutti i passaggi (da zero) effettuati per risolvere un problema di Machine Learning. Per la tua comprensione, ho preso un set di dati semplice ma impegnativo in cui puoi anche progettare le funzionalità a tua discrezione.
Questo progetto è più adatto a persone che hanno una conoscenza di base di Python.
Anche se sei assolutamente nuovo, provalo. E fai domande nei commenti qui sotto.
Processo di previsioni di machine learning
"Continua a tormentare i dati finché non iniziano a rivelare i loro segreti nascosti."
Fare previsioni utilizzando l'apprendimento automatico non significa solo acquisire i dati e fornirli agli algoritmi. L'algoritmo potrebbe emettere qualche previsione ma non è quello a cui stai mirando.
Il processo è il seguente:
Capire il problema: prima di iniziare a lavorare sui dati, è necessario comprendere il problema che stiamo cercando di risolvere. Se conosci già la soluzione al problema di machine learning, pensa a quali fattori potrebbero svolgere un ruolo fondamentale nella risoluzione del problema e passa al terzo step. Se ancora devi elaborare una strategia o una risoluzione passa al secondo step.
Facciamo qualche ipotesi: Questo è abbastanza importante, ma spesso viene dimenticato. In parole semplici, la generazione di ipotesi si riferisce alla creazione di un insieme di caratteristiche che potrebbero influenzare la variabile obiettivo/target. Possiamo farlo prima di esaminare i dati per evitare pensieri o conclusioni affrettate. Questo passaggio spesso aiuta a creare nuove funzionalità.
Iniziamo a lavorare sui dati: ora, scarichiamo i dati e li esaminiamo. Determina quali funzionalità (possibili standardizazioni o normalizazioni ad esempio) dei dati sono disponibili e quali no. Rispondere a queste domande ci metterà sulla strada giusta.
Creiamo il nostro modello:Utilizzando un algoritmo appropriato, addestriamo il modello sul set di dati specificato.
Valutazione del modello: una volta addestrato il modello, valutiamo le prestazioni del modello utilizzando una metrica di errore adeguata. Qui, cerchiamo anche l'importanza della variabile, cioè quali variabili si sono dimostrate significative nel determinare la variabile di destinazione. Di conseguenza, possiamo selezionare le migliori variabili e addestrare nuovamente il modello.
Testiamo il nostro modello: Infine, testiamo il modello sul set di dati invisibili (dati di test). Seguiremo questo processo nel progetto per arrivare alle nostre previsioni finali. Iniziamo.
1) Capire il problema
Il set di dati per questo progetto è stato preso dal set di appartamenti di Kaggle. Come accennato in precedenza, il set di dati è semplice. Questo progetto mira a prevedere i prezzi delle case (residenziali) ad Ames, USA. In questo caso il nostro problema è andare a creare un modello in grado di predire il prezzo di questi appartamenti in base alle caratteristiche che abbiamo.
2) Facciamo qualche ipotesi
Bene, ora arriva la parte divertente.
Quali fattori riesci a pensare in questo momento che possono influenzare i prezzi delle case? Mentre leggi questo, voglio che tu annoti anche i tuoi fattori.
La definizione di un'ipotesi ha due parti: ipotesi nulla (0) e ipotesi concreta (1). Possono essere intese come:
0 - Non esiste alcun impatto di una particolare caratteristica sulla variabile dipendente.
1 - Esiste un impatto diretto di una caratteristica particolare sulla variabile dipendente.
Sulla base di un criterio decisionale (diciamo, livello di significatività del 5%) definiamo due classi :
"Rifiuto"
"Accetto"
In pratica, durante la creazione del modello cerchiamo valori di probabilità (p). Se il valore p<0.05, Rifiuto e quindi si avvera l'ipotesi nulla. Se p> 0.05 ci troviamo nel caso di ipotesi concreta e quindi quella caratteristica la Accettiamo perchè ha una correlazione con il nostro target. Alcuni fattori a cui posso pensare che influenzano direttamente i prezzi delle case sono i seguenti:
Area della casa
Quanti anni ha la casa
Posizione della casa
Quanto è vicino / lontano il mercato
Connettività della posizione della casa con i trasporti
Quanti piani ha la casa
Quale materiale viene utilizzato nella costruzione
Disponibilità di acqua / elettricità
Area giochi / parchi per bambini (se presenti)
Se la terrazza è disponibile
Se il parcheggio è disponibile
Se la sicurezza è disponibile
…continua a pensare. Sono sicuro che puoi inventarne molti altri oltre a questi.
3) Iniziamo a lavorare sui dati
Puoi scaricare i dati e caricarli nel tuo IDE python.
Il set di dati è costituito da 81 variabili esplicative. Sì, non sarà una passeggiata per chì vorrà approfondire fino in fondo tutto il Dataset. Ma impareremo come gestire così tante variabili. La variabile di destinazione è SalePrice.
Iniziamo a scrivere un po di codice e a divertiamoci.
#Importiamo le librerie necessarie
import numpy as np
import pandas as pd
import seaborn as sns
from scipy import stats
from scipy.stats import norm
import matplotlib.pyplot as plt
#Impostiamo la grandezza del grafico di matplotlib
%matplotlib inline
plt.rcParams['figure.figsize'] = (10.0, 8.0)
#Carichiamo i dati che hai scaricato dal link
train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")
#Stampiamo quante righe e colonne ha il nostro dataset
print ('Train contiene {0} righe e {1} colonne'.format(train.shape[0],train.shape[1]))
print ('----------------------------')
print ('Test contiene {0} righe e {1} colonne'.format(test.shape[0],test.shape[1]))
output :
Train contiene 1460 righe e 81 colonne
----------------------------
Test contiene 1459 righe e 80 colonne
In alternativa, puoi anche controllare le informazioni sul set di dati utilizzando il comando info ().
train.info()
output :
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1460 entries, 0 to 1459
Data columns (total 81 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Id 1460 non-null int64
1 MSSubClass 1460 non-null int64
2 MSZoning 1460 non-null object
3 LotFrontage 1201 non-null float64
.....
77 YrSold 1460 non-null int64
78 SaleType 1460 non-null object
79 SaleCondition 1460 non-null object
80 SalePrice 1460 non-null int64
dtypes: float64(3), int64(35), object(43)
memory usage: 924.0+ KB
Controlliamo se il set di dati ha valori mancanti. Questo è molto importante perchè in alcuni casi questi dati vengono completamente ignorati o scartati. In questo caso noi ci concentreremo solo sulle variabile numeriche e non nulle.
train.columns[train.isnull().any()]
Output:
Index(['LotFrontage', 'Alley', 'MasVnrType', 'MasVnrArea', 'BsmtQual', 'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinType2', 'Electrical', 'FireplaceQu', 'GarageType', 'GarageYrBlt', 'GarageFinish', 'GarageQual', 'GarageCond', 'PoolQC', 'Fence', 'MiscFeature'], dtype='object')
Procediamo e controlliamo la distribuzione della variabile target.
#Distribuzione della variabile target
sns.distplot(train['SalePrice'])
Output:
Vediamo che la variabile target SalePrice ha una distribuzione asimmetrica a destra. Avremo bisogno di registrare la trasformazione di questa variabile in modo che diventi normalmente distribuita. Una variabile target normalmente distribuita (o vicina al normale) aiuta a modellare meglio la relazione tra le variabili target e indipendenti. Inoltre, gli algoritmi lineari assumono una varianza costante nel termine di errore. In alternativa, possiamo anche confermare questo comportamento distorto utilizzando la metrica di asimmetria.
#skewness
print "Il skewness del prezzo è {}".format(train['SalePrice'].skew())
Output:
The skewness of SalePrice is 1.88287575977
Registriamo la trasformazione di questa variabile e vediamo se la distribuzione di questa variabile può avvicinarsi alla normalità.
#Trasformiamo la variabile di target
target = np.log(train['SalePrice'])
print('Skewness è', target.skew())
sns.distplot(target)
Output:
Skewness is 0.12133506220520406)
Come hai visto, la trasformazione logaritmica della variabile target ci ha aiutato a correggere la sua distribuzione asimmetrica e la nuova distribuzione sembra più vicina alla normalità. Dato che abbiamo 80 variabili, visualizzarne una per una non sarebbe un approccio astuto. Invece, siccome lo studio risulterebbe molto lungo e complesso ci dedicheremo solo alle variabile numeriche tralasciando le categoriche.
#Separiamo il dataset in altri 2 numerico e categorico
numeric_data = train.select_dtypes(include=[np.number])
cat_data = train.select_dtypes(exclude=[np.number])
print ("ci sono {} colonne numeriche e {} categoriche".format(numeric_data.shape[1],cat_data.shape[1]))
Output:
Ci sono 38 colonne numeriche e 43 categoriche.
Dovremmo rimuovere la variabile Id dai dati numerici.
del numeric_data['Id']
Ora, siamo interessati a conoscere il comportamento di correlazione delle variabili numeriche. Su 38 variabili, presumo che alcune debbano essere correlate. Se trovate, possiamo successivamente rimuovere le variabili non correlate poiché non forniranno alcuna informazione utile al modello.
#correlation plot
corr = numeric_data.corr()
sns.heatmap(corr)
Notare l'ultima riga di questa mappa. Possiamo vedere la correlazione di tutte le variabili con SalePrice. Come puoi vedere, alcune variabili sembrano essere fortemente correlate con la variabile target. Qui, un punteggio di correlazione numerica ci aiuterà a capire meglio il grafico.
print (corr['SalePrice'].sort_values(ascending=False)[:15], '\n') #top 15 variabili correlate
print ('----------------------')
print (corr['SalePrice'].sort_values(ascending=False)[-5:])
#last 5 variabili non correlate
Output:
SalePrice 1.000000
OverallQual 0.790982
GrLivArea 0.708624
GarageCars 0.640409
GarageArea 0.623431
TotalBsmtSF 0.6135811
stFlrSF 0.605852
FullBath 0.560664
TotRmsAbvGrd 0.533723
YearBuilt 0.522897
YearRemodAdd 0.507101
GarageYrBlt 0.486362
MasVnrArea 0.477493
Fireplaces 0.466929
BsmtFinSF1 0.386420
Name: SalePrice, dtype: float64
Qui vediamo che la OverallQual caratteristica è correlata al 79% con la variabile target. Overallqual variabile si riferisce al materiale complessivo e alla qualità dei materiali della casa completata. Bene, anche questo ha senso. Le persone di solito considerano questi parametri per la loro casa dei sogni. Inoltre, GrLivArea è correlato al 70% con la variabile target. GrLivAreasi riferisce alla zona giorno (in sq ft.). Le seguenti variabili mostrano che le persone si preoccupano anche se la casa ha un garage, l'area di quel garage, le dimensioni dell'area seminterrato, ecc.
Tracciamo dei grafici qualitativi per vedere meglio che tipo di correlazioni hanno OverallQual e GrLivAreasi con il nostro target.
Per quanto riguarda la variabile OverallQual procederemo dividendola in classi per poi rappresentarla in funzione del prezzo crescente per vedere cosa accade al prezzo con l'aumentare della qualità dei materiali. Il codice è il seguente
train['OverallQual'].unique()
Output:
array([ 7, 6, 8, 5, 9, 4, 10, 3, 1, 2])
#grafichiamo le 10 classi di OverallQual in corrispondenza del prezzo
pivot = train.pivot_table(index='OverallQual', values='SalePrice', aggfunc=np.median)
pivot.plot(kind='bar', color='red')
Outptu:
Questo comportamento è abbastanza normale. Man mano che la qualità complessiva di una casa aumenta, aumenta anche il suo prezzo di vendita. Visualizziamo la successiva variabile correlata GrLivAreae comprendiamo il loro comportamento.
#GrLivArea
sns.jointplot(x=train['GrLivArea'], y=train['SalePrice'])
Outptu:
Come visto sopra, anche qui vediamo una correlazione diretta della zona giorno con il prezzo di vendita. Tuttavia, possiamo individuare un valore anomalo GrLivArea> 5000. Ho visto valori anomali giocare un ruolo significativo nel rovinare le prestazioni di un modello. Quindi, ce ne sbarazzeremo. Se ti piace questa attività, puoi visualizzare anche altre variabili correlate. Arrivati a questo punto bisognerebbe applicare i ragionamenti fatti per le variabili GrLivAreae e OverallQual per tutte le variabili che abbiamo a disposizione. Essendo questo un articolo di tutorial ci fermeremo a queste due variabili per l'analisi dell'esempio pratico di machine learning per non risultare troppo complesso o pesante per chi è alle prime armi. Ti invito comunque a giocare con le altre variabili e a creare un modello migliore di quello che creeremo all'interno dell'articolo.
Ora elaboriamo le nostre variabili per avere un modello performante.
#rimuoviamo i valori anomali
train.drop(train[train['GrLivArea'] > 4000].index, inplace=True)
train.shape #removed 4 rows`
Output:
(1456, 81)
A questo punto ricreiamo i nostri dataset utilizzando solo le variabili che abbiamo scelto.
Nel nostro caso saranno solo due. Ma ti invito a trovarne altre per rendere il tutto più divertente.
#ridivido le x e y di allenamento e test
newdataset = train[['GrLivArea','OverallQual','SalePrice']]
X_train = train[['GrLivArea','OverallQual']]
y_train = train['SalePrice']
X_test = train[['GrLivArea','OverallQual']]
y_test = train['SalePrice']
Creiamo adesso un Pairplot e la Heatmap per avere una visione più completa delle correlazioni.
sns.pairplot(newdataset)
plt.show()
Output:
4) Creiamo il nostro modello
Ora che abbiamo un idea più concreta del nostro problema, delle ipotesi e che abbiamo lavorato il dato possiamo concentrarci nella creazione del nostro modello.
In questo caso utilizzeremo due modelli diversi.
Utilizzeremo prima il Random_Forest_Regression_Model e successivamente il Linear_Regression_Model così da poter successivamente confrontare i due modelli.
Ho scritto questi due modelli come delle funzioni in modo tale che potrai riutilizzarli con i tuoi dati passandogli solamente il dataset e il target.
Vediamo adesso il Random_Forest_Regression_Model:
def Random_Forest_Regression_Model(dataset,target):
X = dataset.loc[:, dataset.columns != target]
y = dataset[target]
from sklearn.ensemble import RandomForestRegressor
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)
model = RandomForestRegressor(random_state=1)
model.fit(X_train, y_train)
pred = model.predict(X_test)# Visualizing Feature Importance
feat_importances = pd.Series(model.feature_importances_, index=X.columns)
feat_importances.nlargest(25).plot(kind='barh',figsize=(10,10))
plt.show()
y_pred = model.predict(X)
labels = dataset[target]
df_temp = pd.DataFrame({'Previsto': labels, 'Predetto':y_pred})
df_temp.head()# Creating Line Graph
from matplotlib.pyplot import figure
figure(num=None, figsize=(15, 6), dpi=80, facecolor='w', edgecolor='k')
y1 = df_temp['Previsto']
y2 = df_temp['Predetto']
plt.plot(y1, label = 'Previsto')
plt.plot(y2, label = 'Predetto')
plt.legend()
plt.show()
from sklearn.metrics import mean_absolute_error as mae print(f'Errore Medio Assoluto ( MAE ) : {mae(y,y_pred)}')
from sklearn.metrics import mean_squared_error, r2_score
# Mean Error
print('Mean squared error: %.2f' % mean_squared_error(y_pred, y))
# Se il coefficente di determinazione è 1 il modello è perfetto
print('Coefficient of determination: %.2f' % r2_score(y_pred, y))
return model
modelloRfM = Random_Forest_Regression_Model(newdataset,'SalePrice')
Output:
Errore Medio Assoluto ( MAE ) : 16674.011430222203
Mean squared error: 639043357.06
Coefficient of determination: 0.88
Passiamo ora alla regressione lineare. In realtà non andrai ad usare più modelli solitamente ma in questo caso ne vedremmo due per poi paragonarli e capire quali sono gli indicatori che ci aiutano a capire quale sia il migliore.
Volendo in questo caso avere un modello performante ed un modello non performante effettueremo lo regressione utilizzando solo GrLivArea e il target SalePrice.
Scriviamo il codice ed eseguiamolo
def visualizza_Linear_Regression_Model(dataset, target):
X = dataset.loc[:, dataset.columns != target]
y = dataset[target]
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error as mae
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
model = LinearRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X)
from matplotlib.pyplot import figure
# Plot outputs
plt.scatter(X, y, color='black')
plt.plot(X, y_pred, color='blue', linewidth=3)
plt.xticks(())
plt.yticks(())
plt.show()
from sklearn.metrics import mean_squared_error, r2_score
# Stampiamo il coefficente
print('Coefficients: \n', model.coef_)
# Mean Error
print('Mean squared error: %.2f' % mean_squared_error(y_pred, y))
# Se il coefficente di determinazione è 1 il modello è perfetto
print('Coefficient of determination: %.2f' % r2_score(y_pred, y))
return model
modelloLM = visualizza_Linear_Regression_Model(newdataset[['GrLivArea','SalePrice']],'SalePrice')
Output:
Coefficients:
[111.91917371]
Mean squared error: 2827781279.81
Coefficient of determination: 0.08
5) Valutiamo i Modelli
Arrivati a questo punto, dove esserci divertiti a scrivere codice e a rubare ai dati informazioni nascoste, arriva un momento molto importante:
"Dobbiamo capire quanto il nostro modello è affidabile"
Riportiamo qui sotto i dati che abbiamo calcolato.
Come ci salta subito all'occhio il Random Forest Model è il modello più affidabile. Proprio come volevamo.
Solitamente quando si valuta un modello esistono diversi tipi di metriche che è possibile utilizzare. Io solitamente consiglio di utilizzare sempre questi tre campi, perche secondo un mio parere ci danno una visione generale sulle capacità del modello.
6) Testiamo il modello
Questo passaggio è fondamentale su vuoi capire a pieno quali sono i punti di "certezza" e "incertezza" del modello che hai creato. Nel nostro caso sarebbe inutile andare ad effettuare delle previsioni con i modelli che abbiamo creato, poichè, anche se "sembra" affidabile all'88% il nostro modello è stato allenato su un set molto ristretto di caratteristche e quindi non rispecchia nemmeno vagamente la realtà degli appartamenti Americani.
Arrivati a questo punto il Tutorial è terminato. Ti consiglio di non fermarti qui ma di espandere il progetto fino a dove riesci, utilizzando tutte le variabile che ritieni fondamentali per stimare il prezzo di questi appartamenti. Per qualsiasi Problema o Errore Scrivilo qui nei commenti oppure fai una domanda nel forum. Il nostro Team di Esperti di AI è pronto ad aiutarti.
Per scaricare gratuitamente devi prima registrati/accede al portale.
Scorri in fondo alla pagina per registrati o accedere
Sostienici condividendo e commentando l'articolo, Grazie !
Complimenti per la chiarezza espositiva che sembra persino rendere semplici i concetti che invece a mio giudizio... non lo sono... Gran bell'esempio applicativo!