Regressione lineare TensorFlow con termine di sfaccettatura e interazione

⚡ Riepilogo intelligente

La regressione lineare sui dati relativi al mercato immobiliare di Boston migliora quando vengono individuati prima i termini di interazione corretti. Google Facets mette in evidenza visivamente queste relazioni e due caratteristiche incrociate hanno ridotto la perdita del test TensorFlow da 1650 a 1515.

  • 🔘 I dati prima di tutto: Comprendere le distribuzioni e i valori anomali è fondamentale prima di elaborare qualsiasi modello, perché un modello non fa altro che generalizzare uno schema già individuato.
  • ☑️ Panoramica delle sfaccettature: Le statistiche per singola caratteristica mettono in evidenza i valori mancanti, le colonne con un'elevata presenza di zeri e le discrepanze nella distribuzione tra i dati di training e di test, il tutto in un'unica tabella.
  • Analisi approfondita delle sfaccettature: La suddivisione in categorie X e Y trasforma le relazioni a tre vie in un grafico bidimensionale leggibile, colorato in base al quartile di prezzo.
  • 🧪 Lettura di correlazione: La mappa di calore e la griglia di accoppiamento segnalano INDUS con NOX e DIS con entrambi come potenziali candidati all'interazione.
  • Standardizzazione: preprocessing.scale centra le dodici colonne continue prima che vengano elaborate dallo stimatore, lasciando inalterate CHAS e PRICE.
  • 📈 Guadagno misurato: L'aggiunta di INDUS_NOS e INDUS_NOS_DIS sposta la perdita media da 86.89361 a 79.78876 sul set di test.

Regressione lineare con TensorFlow, con sfaccettatura e termine di interazione

Regressione lineare TensorFlow

In questo tutorial imparerai come controllare i dati e prepararli per creare una semplice attività di regressione lineare.

Questo tutorial è diviso in due parti:

  • Cerca l'interazione
  • Prova il modello

Nel tutorial precedente, hai utilizzato il set di dati di Boston per stimare il prezzo medio di una casa. Il set di dati di Boston ha dimensioni ridotte, con solo 506 osservazioni. Questo set di dati è considerato un punto di riferimento per provare nuovi algoritmi di regressione lineare.

Il dataset è composto da:

Variabile Descrizione
zn La percentuale di terreno residenziale suddiviso in zone per lotti superiori a 25,000 piedi quadrati.
Indus La proporzione di acri commerciali non al dettaglio per città.
nox concentrazione di ossidi nitrici
rm numero medio di stanze per abitazione
la percentuale di unità abitative costruite prima del 1940
DIS distanze ponderate da cinque centri per l'impiego di Boston
imposta aliquota dell'imposta sulla proprietà a valore intero per dollari 10,000
ptratio il rapporto alunni-insegnanti per città
medv Il valore medio delle case occupate dai proprietari in migliaia di dollari
criminale tasso di criminalità pro capite per città
Chas Variabile fittizia Charles River (1 se delimita il fiume; 0 altrimenti)
B la percentuale di neri nella città

In questo tutorial stimeremo il prezzo mediano utilizzando un regressore lineare, ma l'attenzione si concentrerà su un particolare processo di machine learning: “preparazione dei dati”.

Un modello generalizza il modello nei dati. Per catturare un modello del genere, devi prima trovarlo. Una buona pratica è eseguire un'analisi dei dati prima di eseguire qualsiasi algoritmo di machine learning.

Scegliere le caratteristiche giuste fa la differenza nel successo del tuo modello. Immagina di provare a stimare il salario di un popolo, se non includi il genere come covariata, ti ritroverai con una stima inadeguata.

Un altro modo per migliorare il modello è osservare la correlazione tra la variabile indipendente. Tornando all’esempio, si può pensare all’istruzione come un ottimo candidato per prevedere il salario ma anche l’occupazione. È giusto dire che l'occupazione dipende dal livello di istruzione, vale a dire che l'istruzione superiore spesso porta a un'occupazione migliore. Se generalizziamo questa idea, possiamo dire che la correlazione tra la variabile dipendente e una variabile esplicativa può essere amplificata da un'altra variabile esplicativa.

Per catturare l’effetto limitato dell’istruzione sull’occupazione, possiamo usare un termine di interazione.

Termine di interazione tra istruzione e occupazione illustrato su una curva salariale

Se osserviamo l’equazione salariale, diventa:

Equazione salariale estesa con un termine di interazione tra istruzione e occupazione

If Simbolo del coefficiente beta per il termine di interazione è positivo, allora implica che un ulteriore livello di istruzione produce un aumento maggiore del valore mediano di una casa per un alto livello di occupazione. In altre parole, esiste un effetto di interazione tra istruzione e occupazione.

La stessa famiglia di stimatori alimenta anche il classificatore lineare quando l'etichetta è una classe anziché un prezzo. In questo tutorial, cercheremo di capire quali variabili possono essere dei buoni candidati per i termini di interazione. Verificheremo se l'aggiunta di questo tipo di informazioni porta a una migliore previsione dei prezzi.

Statistiche riassuntive

Prima di procedere con la creazione del modello, è possibile seguire alcuni passaggi. Come accennato in precedenza, il modello è una generalizzazione dei dati. La prassi migliore è comprendere prima i dati e poi formulare una previsione. Se non si conoscono i dati, le possibilità di migliorare il modello sono scarse.

Come primo passaggio, caricare i dati come dataframe panda e creare un set di addestramento e un set di test.

Suggerimenti: per questo tutorial, è necessario avere matplotlib e seaborn installati in Python. Puoi installare un Python pacchetto al volo con Jupyter. È Non dovrebbe fare questo

!conda install -- yes matplotlib

ma

import sys
!{sys.executable} -m pip install matplotlib # Already installed
!{sys.executable} -m pip install seaborn 

Tieni presente che questo passaggio non è necessario se hai installato matplotlib e seaborn.

Matplotlib è la libreria in cui creare un grafico PythonSeaborn è una libreria di visualizzazione statistica basata su matplotlib. Fornisce atractrame avvincenti e bellissime.

Il codice seguente importa le librerie necessarie.

import pandas as pd
from sklearn import datasets
import tensorflow as tf
from sklearn.datasets import load_boston
import numpy as np

La libreria sklearn include il set di dati di Boston. Puoi chiamare la sua API per importare i dati.

Nota sulla versione: load_boston è stato deprecato in scikit-learn 1.0 e rimosso in scikit-learn 1.2 perché il dataset codifica una caratteristica con connotazioni razziali. Su un'installazione corrente, utilizzare fetch_california_housing In alternativa, puoi caricare il file raw manualmente. Il flusso di lavoro mostrato di seguito rimane invariato; cambia solo il caricatore.

boston = load_boston()
df = pd.DataFrame(boston.data)

I nomi delle caratteristiche sono memorizzati nell'oggetto feature_names come un array.

boston.feature_names

Uscita

array(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT'], dtype='<U7')

Puoi rinominare le colonne.

df.columns = boston.feature_names
df['PRICE'] = boston.target
df.head(2)

Prime due righe del DataFrame di Boston dopo aver rinominato le colonne

Converti la variabile CHAS come variabile stringa e etichettala con sì se CHAS = 1 e no se CHAS = 0

df['CHAS'] = df['CHAS'].map({1:'yes', 0:'no'})
df['CHAS'].head(5)
0    no
1    no
2    no
3    no
4    no
Name: CHAS, dtype: object

Con i panda, è semplice dividere il set di dati. Dividi in modo casuale il set di dati con l'80% di set di addestramento e il 20% di set di test. Pandas Dispone di una funzione di campionamento integrata per suddividere un data frame.

Il primo parametro frac è un valore compreso tra 0 e 1. Lo imposti su 0.8 per selezionare casualmente l'80% del frame di dati.

random_state corregge la randomizzazione, in modo che vengano restituite le stesse righe a tutti.

### Create train/test set
df_train=df.sample(frac=0.8,random_state=200)
df_test=df.drop(df_train.index)

È possibile ottenere la forma dei dati. Dovrebbe essere:

  • Trenino elettrico: 506*0.8 = 405
  • Set di prova: 506*0.2 = 101
print(df_train.shape, df_test.shape)

Uscita

(405, 14) (101, 14)
df_test.head(5)

Uscita

CRIM ZN INDOS CHAS NOX RM ETÀ DIS RAD TAX PTRAZIONE B LSTAT PREZZO
0 0.00632 18.0 2.31 no 0.538 6.575 65.2 4.0900 1.0 296.0 15.3 396.90 4.98 24.0
1 0.02731 0.0 7.07 no 0.469 6.421 78.9 4.9671 2.0 242.0 17.8 396.90 9.14 21.6
3 0.03237 0.0 2.18 no 0.458 6.998 45.8 6.0622 3.0 222.0 18.7 394.63 2.94 33.4
6 0.08829 12.5 7.87 no 0.524 6.012 66.6 5.5605 5.0 311.0 15.2 395.60 12.43 22.9
7 0.14455 12.5 7.87 no 0.524 6.172 96.1 5.9505 5.0 311.0 15.2 396.90 19.15 27.1

I dati sono disordinati; è spesso sbilanciato e cosparso di valori anomali che ostacolano l'analisi e la formazione sull'apprendimento automatico.

Il primo passo per ripulire il set di dati è capire dove è necessario pulirlo. Ripulire un set di dati può essere complicato, soprattutto in qualsiasi modo generalizzabile

Migliori Google Il team di ricerca ha sviluppato uno strumento per questo lavoro chiamato sfaccettature Questo strumento ti aiuta a visualizzare i dati e ad analizzarli in vari modi. È un buon punto di partenza per comprendere la struttura del set di dati.

Facets ti permette di individuare i casi in cui i dati non corrispondono esattamente alle tue aspettative.

Ad eccezione della loro applicazione web, Google rende facile incorporare il toolkit in un Jupyter taccuino.

Ci sono due parti in Facets:

  • Panoramica delle sfaccettature
  • Approfondimento sulle sfaccettature

Panoramica delle sfaccettature

Facets Overview fornisce una panoramica del set di dati. Facets Overview divide le colonne dei dati in righe di informazioni salienti che mostrano

  1. la percentuale di osservazione mancante
  2. valori minimo e massimo
  3. statistiche come media, mediana e deviazione standard.
  4. Aggiunge inoltre una colonna che mostra la percentuale di valori che sono zero, il che è utile quando la maggior parte dei valori sono zero.
  5. È possibile vedere queste distribuzioni sul set di dati di test e sul set di training per ogni feature. Ciò significa che puoi ricontrollare che il test abbia una distribuzione simile ai dati di training.

Questo è almeno il minimo da fare prima di qualsiasi attività di machine learning. Con questo strumento non si perde questo passaggio fondamentale e si evidenziano alcune anomalie.

Approfondimento sulle sfaccettature

Facets Deep Dive è uno strumento fantastico. Ti permette di ottenere maggiore chiarezza sul tuo set di dati e di ingrandire fino a visualizzare un singolo dato. In pratica, puoi scomporre i dati per riga e colonna in base a qualsiasi caratteristica del set di dati.

Utilizzeremo questi due strumenti con il set di dati di Boston.

Note:: non è possibile utilizzare Panoramica sfaccettature e Approfondimento sfaccettature contemporaneamente. È necessario prima pulire il notebook per cambiare lo strumento.

Prima di poter utilizzare entrambi gli strumenti, Facets deve essere installato nell'ambiente del notebook.

Installa sfaccettatura

È possibile utilizzare l'app Web Facet per la maggior parte dell'analisi. In questo tutorial vedrai come usarlo all'interno di a Jupyter Taccuino.

Prima di tutto, devi installare nbextensions. Si fa con questo codice. Copia e incolla il seguente codice nel terminale della tua macchina.

pip install jupyter_contrib_nbextensions

Subito dopo, devi clonare i repository sul tuo computer. Hai due scelte:

Opzione 1) Copia e incolla questo codice nel terminale (Consigliata)

Se non hai Git installato sul tuo computer, vai a questo URL Ottieni per Windows pagina di download e seguire le istruzioni. Una volta terminato, puoi utilizzare il comando git nel terminale per l'utente Mac o il prompt di Anaconda Windows Utente

git clone https://github.com/PAIR-code/facets

Opzione 2) Vai su il repository PAIR-code/facets e scaricare i repository.

Pagina del repository delle sfaccettature del codice PAIR su GitHub

La pagina del repository qui sopra contiene il pulsante di download utilizzato per l'opzione 2. Se scegli la prima opzione, il file verrà salvato nella cartella di download. Puoi lasciare che il file venga scaricato oppure trascinarlo in un altro percorso.

Puoi verificare dove sono archiviati i Facet con questa riga di comando:

echo `pwd`/`ls facets`

Ora che hai individuato Facets, devi installarlo Jupyter Taccuino. È necessario impostare la directory di lavoro sul percorso in cui si trovano i facet.

La directory di lavoro attuale e la posizione del file zip di Facets dovrebbero essere le stesse.

Terminale che mostra la cartella facets nella directory di lavoro corrente

L'output del terminale qui sopra conferma che facets si trova nella directory di lavoro corrente. È necessario impostare la directory di lavoro su Facet:

cd facets

Per installare Facets in Jupyter, hai due opzioni. Se hai installato Jupyter con Conda per tutti gli utenti, copia questo codice:

jupyter nbextension install facets-dist/

Altrimenti usa:

jupyter nbextension install facets-dist/ --user

Va bene, è tutto a posto. Apriamo Panoramica delle faccette.

Panoramica delle sfaccettature di esecuzione in Jupyter

Panoramica utilizza a Python script per calcolare le statistiche. Devi importare lo script denominato generic_feature_statistics_generator in Jupyter. Non preoccuparti; lo script si trova nei file delle sfaccettature.

È necessario individuare il suo percorso. È facile da fare. Apri facets, apri il file facets_overview e poi python. Copia il percorso

Percorso del file della cartella python facets_overview

Dopodiché, torna a Jupytere scrivi il seguente codice. Cambia il percorso '/Users/Thomas/facets/facets_overview/python' nel tuo percorso.

# Add the facets overview python code to the python path# Add t 
import sys
sys.path.append('/Users/Thomas/facets/facets_overview/python')

Puoi importare lo script con il codice seguente.

from generic_feature_statistics_generator import 
GenericFeatureStatisticsGenerator

In Windows, lo stesso codice diventa

import sys
sys.path.append(r"C:\Users\Admin\Anaconda3\facets-master\facets_overview\python")

from generic_feature_statistics_generator import GenericFeatureStatisticsGenerator

Per calcolare le statistiche delle funzionalità, è necessario utilizzare la funzione GenericFeatureStatisticsGenerator() e utilizzi l'oggetto ProtoFromDataFrames. Puoi passare il frame di dati in un dizionario. Se ad esempio vogliamo creare una statistica riepilogativa per il convoglio, possiamo memorizzare le informazioni in un dizionario e utilizzarle nell'oggetto "ProtoFromDataFrames"

'name': 'train', 'table': df_train

Nome è il nome della tabella visualizzata e si utilizza il nome della tabella di cui si desidera calcolare il riepilogo. Nel tuo esempio, la tabella contenente i dati è df_train

# Calculate the feature statistics proto from the datasets and stringify it for use in facets overview
import base64

gfsg = GenericFeatureStatisticsGenerator()

proto = gfsg.ProtoFromDataFrames([{'name': 'train', 'table': df_train},
                                  {'name': 'test', 'table': df_test}])

#proto = gfsg.ProtoFromDataFrames([{'name': 'train', 'table': df_train}])
protostr = base64.b64encode(proto.SerializeToString()).decode("utf-8")

Infine, basta copiare e incollare il codice qui sotto. Il codice proviene direttamente da GitHub. Dovresti essere in grado di vedere questo:

Tabella riassuntiva delle caratteristiche: statistiche di riepilogo per ciascuna caratteristica

# Display the facets overview visualization for this data# Displ 
from IPython.core.display import display, HTML

HTML_TEMPLATE = """<link rel="import" href="/nbextensions/facets-dist/facets-jupyter.html" >
        <facets-overview id="elem"></facets-overview>
        <script>
          document.querySelector("#elem").protoInput = "{protostr}";
        </script>"""
html = HTML_TEMPLATE.format(protostr=protostr)
display(HTML(html))

Grafico di correlazione e griglia di coppie

Dopo aver analizzato i dati e la loro distribuzione, è possibile tracciare una matrice di correlazione. La matrice di correlazione calcola il coefficiente di Pearson. Questo coefficiente è compreso tra -1 e 1, dove un valore positivo indica una correlazione positiva e un valore negativo una correlazione negativa.

Sei interessato a vedere quali variabili possono essere un buon candidato per i termini di interazione.

Nota sulla versione: la maschera sottostante chiama np.bool, un alias che è stato deprecato in NumPy 1.20 e rimosso in NumPy 1.24. Su un recente NumPy la stessa riga genera AttributeError: module 'numpy' has no attribute 'bool'; l'integrato bool è un ricambio compatibile.

## Choose important feature and further check with Dive
%matplotlib inline  
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="ticks")
# Compute the correlation matrix
corr = df.corr('pearson')
# Generate a mask for the upper triangle
mask = np.zeros_like(corr, dtype=np.bool)
mask[np.triu_indices_from(mask)] = True
# Set up the matplotlib figure
f, ax = plt.subplots(figsize=(11, 9))

# Generate a custom diverging colormap
cmap = sns.diverging_palette(220, 10, as_cmap=True)

# Draw the heatmap with the mask and correct aspect ratio
sns.heatmap(corr, mask=mask, cmap=cmap, vmax=.3, center=0,annot=True,
            square=True, linewidths=.5, cbar_kws={"shrink": .5})

Uscita

<matplotlib.axes._subplots.AxesSubplot at 0x1a184d6518>

Mappa di calore della correlazione di Seaborn delle variabili di Boston

Nella mappa di calore qui sopra, i quadrati più scuri indicano correlazioni più forti. Dalla matrice si può notare:

  • LSTAT
  • RM

Sono fortemente correlati con il PREZZO. Un'altra caratteristica interessante è la forte correlazione positiva tra NOX e INDUS, il che significa che queste due variabili si muovono nella stessa direzione. Entrambe sono anche correlate con il PREZZO. DIS è fortemente correlato anche con INDUS e NOX.

Hai un primo indizio che INDUS e NOX potrebbero essere buoni candidati per un termine di interazione e potrebbe essere interessante concentrarsi anche su DIS.

Puoi andare un po' più in profondità tracciando una griglia di coppia. Illustrerà più in dettaglio la mappa di correlazione tracciata in precedenza.

La griglia di coppie è composta come segue:

  • Parte superiore: grafico a dispersione con linea montata
  • Diagonale: grafico della densità del kernel
  • Parte inferiore: grafico multivariato della densità del kernel

Ci si concentra su quattro variabili indipendenti. La scelta corrisponde alle variabili con una forte correlazione con il PREZZO.

  • INDOS
  • NOX
  • RM
  • LSTAT

inoltre, il PREZZO.

Note: che l'errore standard viene aggiunto per impostazione predefinita al grafico a dispersione.

attributes = ["PRICE", "INDUS", "NOX", "RM", "LSTAT"]

g = sns.PairGrid(df[attributes])
g = g.map_upper(sns.regplot, color="g")
g = g.map_lower(sns.kdeplot,cmap="Reds", shade=True, shade_lowest=False)
g = g.map_diag(sns.kdeplot)

Uscita

Griglia di coppie Seaborn di PRICE, INDUS, NOX, RM e LSTAT

Cominciamo dalla parte superiore:

  • Il prezzo è correlato negativamente con INDUS, NOX e LSTAT; correlato positivamente con RM.
  • Esiste una leggera non linearità tra LSTAT e PRICE
  • C'è come una linea retta quando il prezzo è uguale a 50. Dalla descrizione del dataset, PRICE è stato troncato al valore di 50

Diagonale: Il NOX sembra avere due cluster, uno intorno a 0.5 e uno intorno a 0.85.

Per verificarlo meglio, puoi guardare la parte inferiore. La densità multivariata del kernel è interessante in un certo senso colora dove si trova la maggior parte dei punti. La differenza con il grafico a dispersione traccia una densità di probabilità, anche se non esiste alcun punto nel set di dati per una determinata coordinata. Quando il colore è più forte, indica un'alta concentrazione di punti intorno a quest'area.

Se controlli la densità multivariata per INDUS e NOX, puoi vedere la correlazione positiva e i due cluster. Quando la quota del settore è superiore a 18, la concentrazione di ossidi di azoto è superiore a 0.6.

Puoi pensare di aggiungere un'interazione tra INDUS e NOX nella relazione lineare.

Infine, puoi utilizzare il secondo strumento creato da GoogleAnalisi dettagliata delle sfaccettature. L'interfaccia è suddivisa in quattro sezioni principali. L'area centrale mostra i dati in una visualizzazione zoomabile. Nella parte superiore del pannello, è presente un menu a tendina che consente di modificare la disposizione dei dati, controllando la suddivisione in sfaccettature, il posizionamento e il colore. A destra, è presente una visualizzazione dettagliata di una specifica riga di dati. Ciò significa che è possibile fare clic su qualsiasi punto dati nella visualizzazione centrale per visualizzare i dettagli relativi a quel particolare punto dati.

Durante la fase di visualizzazione dei dati, sei interessato a cercare la correlazione a coppie tra la variabile indipendente sul prezzo della casa. Tuttavia, coinvolge almeno tre variabili e i grafici 3D sono complicati da usare.

Un modo per affrontare questo problema è creare una variabile categoriale. Ovvero, possiamo creare un grafico bidimensionale e colorare i punti. È possibile suddividere la variabile PREZZO in quattro categorie, ciascuna corrispondente a un quartile (ad esempio, 0.25, 0.5, 0.75). Questa nuova variabile si chiamerà Q_PREZZO.

## Check non linearity with important features
df['Q_PRICE'] =  pd.qcut(df['PRICE'], 4, labels=["Lowest", "Low", "Upper", "upper_plus"])
## Show non linearity between RM and LSTAT
ax = sns.lmplot(x="DIS", y="INDUS", hue="Q_PRICE", data=df, fit_reg = False,palette="Set3")

Grafico a dispersione di DIS rispetto a INDUS colorato in base al quartile di prezzo

Analisi approfondita di Facets

Per aprire Deep Dive, è necessario trasformare i dati in formato JSON. Pandas dispone di un metodo per farlo: chiama to_json sul DataFrame.

La prima riga di codice imposta le dimensioni dello sprite in base al numero di righe contenute nel dataset.

df['Q_PRICE'] =  pd.qcut(df['PRICE'], 4, labels=["Lowest", "Low", "Upper", "upper_plus"])
sprite_size = 32 if len(df.index)>50000 else 64
jsonstr = df.to_json(orient='records')

Il codice seguente proviene da Google GitHub. Dopo aver eseguito il codice, dovresti visualizzare questo:

Analisi approfondita delle sfaccettature: visualizzazione a dispersione sfaccettata del dataset di Boston.

# Display thde Dive visualization for this data
from IPython.core.display import display, HTML

# Create Facets template  
HTML_TEMPLATE = """<link rel="import" href="/nbextensions/facets-dist/facets-jupyter.html">
        <facets-dive sprite-image-width="{sprite_size}" sprite-image-height="{sprite_size}" id="elem" height="600"></facets-dive>
        <script>
          document.querySelector("#elem").data = {jsonstr};
        </script>"""

# Load the json dataset and the sprite_size into the template
html = HTML_TEMPLATE.format(jsonstr=jsonstr, sprite_size=sprite_size)

# Display the template
display(HTML(html))

Ti interessa vedere se esiste una connessione tra il tasso di settore, la concentrazione di ossidi, la distanza dal centro per l'impiego e il prezzo della casa.

Per questo, per prima cosa dividi i dati per fascia di settore e colore con il quartile del prezzo:

  • Seleziona la sfaccettatura X e scegli INDUS.
  • Seleziona Visualizza e scegli DIS. Colorerà i punti con il quartile del prezzo della casa

Qui, i colori più scuri indicano una maggiore distanza dal primo centro per l'impiego.

Finora, mostra ancora una volta ciò che sai, tasso di settore più basso, prezzo più alto. Ora potete vedere la ripartizione per INDUX e per NOX.

Seleziona la sfaccettatura Y e scegli NOX.

Ora puoi vedere che la casa lontana dal primo centro di lavoro ha la quota di settore più bassa e quindi la concentrazione di ossido più bassa. Se scegli di visualizzare il tipo con Q_PRICE e ingrandisci l'angolo in basso a sinistra, puoi vedere di che tipo di prezzo si tratta.

Hai un altro indizio che l’interazione tra IND, NOX e DIS può essere un buon candidato per migliorare il modello.

L'esplorazione ha individuato due possibili interazioni, quindi il prossimo passo è testarle in un modello reale.

Regressione lineare con TensorFlow

In questa sezione, stimerai il modello di regressione lineare con il TensorFlow API di stima. Procederai come segue:

  • Prepara i dati
  • Stimare un modello di riferimento: nessuna interazione
  • Stimare un modello con interazione

Nota sulla versione: , il tf-estimator Il pacchetto ha rilasciato la sua versione finale con TensorFlow 2.15 ed è assente da TensorFlow 2.16 in poi, quindi tf.estimator.LinearRegressor Funziona solo con TensorFlow 1.x, a meno che non si effettui la migrazione a un modello lineare Keras.

Ricorda, l'obiettivo del machine learning è minimizzare l'errore. In questo caso, il modello con l'errore quadratico medio più basso risulterà vincente. L'estimatore di TensorFlow calcola automaticamente questa metrica.

Dati di preparazione

Nella maggior parte dei casi, è necessario trasformare i dati. Ecco perché la Panoramica delle sfaccettature è così interessante. Come si può notare dalle statistiche riassuntive, sono presenti dei valori anomali. Questi valori influenzano le stime perché non rispecchiano la popolazione analizzata. I valori anomali tendono a distorcere i risultati. Ad esempio, un valore anomalo positivo tende a sovrastimare il coefficiente.

Una buona soluzione per affrontare questo problema è standardizzare la variabile. La standardizzazione significa una deviazione standard di uno e una media di zero. Il processo di standardizzazione prevede due fasi. Prima di tutto, si sostituiscetracts è il valore medio della variabile. In secondo luogo, divide per la deviazione standard in modo che la distribuzione abbia una deviazione standard unitaria.

La Biblioteca scikit-impara è utile per standardizzare le variabili. A tale scopo è possibile utilizzare il modulo di preelaborazione con la scala degli oggetti.

È possibile utilizzare la funzione seguente per ridimensionare un set di dati. Tieni presente che non ridimensioni la colonna dell'etichetta e le variabili categoriali.

from sklearn import preprocessing
def standardize_data(df): 
    X_scaled = preprocessing.scale(df[['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD',
       'TAX', 'PTRATIO', 'B', 'LSTAT']])
    X_scaled_df = pd.DataFrame(X_scaled, columns = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD',
       'TAX', 'PTRATIO', 'B', 'LSTAT'])
    df_scale = pd.concat([X_scaled_df,
                       df['CHAS'],
                       df['PRICE']],axis=1, join='inner')
    return df_scale

È possibile utilizzare la funzione per costruire il set di treno/test in scala.

df_train_scale = standardize_data(df_train)
df_test_scale = standardize_data(df_test)

Regressione di base: benchmark

Prima di tutto, alleni e testi un modello senza interazione. Lo scopo è vedere la metrica delle prestazioni del modello.

Il modo per addestrare il modello è esattamente come nel tutorial su API di alto livello. Utilizzerai lo stimatore TensorFlow LinearRegressor.

Come promemoria, devi scegliere:

  • le caratteristiche da inserire nel modello
  • trasformare le caratteristiche
  • costruire il regressore lineare
  • costruire la funzione input_fn
  • addestrare il modello
  • testare il modello

Per addestrare il modello si utilizzano tutte le variabili presenti nel dataset. In totale, ci sono dodici variabili continue e una variabile categorica.

## Add features to the bucket: 
### Define continuous list
CONTI_FEATURES  = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT']
CATE_FEATURES = ['CHAS']

Converti le funzionalità in una colonna numerica o in una colonna categoriale

continuous_features = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES]
#categorical_features = tf.feature_column.categorical_column_with_hash_bucket(CATE_FEATURES, hash_bucket_size=1000)
categorical_features = [tf.feature_column.categorical_column_with_vocabulary_list('CHAS', ['yes','no'])]

Crei il modello con linearRegressor. Memorizzi il modello nella cartella train_Boston

model = tf.estimator.LinearRegressor(    
	model_dir="train_Boston",     
    feature_columns=categorical_features + continuous_features)

Uscita

INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'train_Boston', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x1a19e76ac8>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

Ogni colonna nei dati di training o di test viene convertita in un tensore con la funzione get_input_fn

FEATURES = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT', 'CHAS']
LABEL= 'PRICE'
def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True):
    return tf.estimator.inputs.pandas_input_fn(
       x=pd.DataFrame({k: data_set[k].values for k in FEATURES}),
       y = pd.Series(data_set[LABEL].values),
       batch_size=n_batch,   
       num_epochs=num_epochs,
       shuffle=shuffle)

Stimi il modello sui dati del treno.

model.train(input_fn=get_input_fn(df_train_scale, 
                                      num_epochs=None,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)

Uscita

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 1 into train_Boston/model.ckpt.
INFO:tensorflow:loss = 56417.703, step = 1
INFO:tensorflow:global_step/sec: 144.457
INFO:tensorflow:loss = 76982.734, step = 101 (0.697 sec)
INFO:tensorflow:global_step/sec: 258.392
INFO:tensorflow:loss = 21246.334, step = 201 (0.383 sec)
INFO:tensorflow:global_step/sec: 227.998
INFO:tensorflow:loss = 30534.78, step = 301 (0.439 sec)
INFO:tensorflow:global_step/sec: 210.739
INFO:tensorflow:loss = 36794.5, step = 401 (0.477 sec)
INFO:tensorflow:global_step/sec: 234.237
INFO:tensorflow:loss = 8562.981, step = 501 (0.425 sec)
INFO:tensorflow:global_step/sec: 238.1
INFO:tensorflow:loss = 34465.08, step = 601 (0.420 sec)
INFO:tensorflow:global_step/sec: 237.934
INFO:tensorflow:loss = 12241.709, step = 701 (0.420 sec)
INFO:tensorflow:global_step/sec: 220.687
INFO:tensorflow:loss = 11019.228, step = 801 (0.453 sec)
INFO:tensorflow:global_step/sec: 232.702
INFO:tensorflow:loss = 24049.678, step = 901 (0.432 sec)
INFO:tensorflow:Saving checkpoints for 1000 into train_Boston/model.ckpt.
INFO:tensorflow:Loss for final step: 23228.568.


<tensorflow.python.estimator.canned.linear.LinearRegressor at 0x1a19e76320>

Infine, si stimano le prestazioni del modello sul test set

model.evaluate(input_fn=get_input_fn(df_test_scale, 
                                      num_epochs=1,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)

Uscita

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-05-29-02:40:43
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train_Boston/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Finished evaluation at 2018-05-29-02:40:43
INFO:tensorflow:Saving dict for global step 1000: average_loss = 86.89361, global_step = 1000, loss = 1650.9785


{'average_loss': 86.89361, 'global_step': 1000, 'loss': 1650.9785}

La perdita del modello è 1650.9785. Questa è la metrica da battere nella sezione successiva

Migliorare il modello: termine di interazione

Nella prima parte del tutorial, avete osservato un'interessante relazione tra le variabili. Le diverse tecniche di visualizzazione hanno rivelato che INDUS e NOX sono collegate e amplificano reciprocamente il loro effetto sul prezzo. Non solo l'interazione tra INDUS e NOX influenza il prezzo, ma questo effetto è anche più forte quando interagisce con DIS.

È giunto il momento di generalizzare questa idea e verificare se è possibile migliorare la capacità predittiva del modello.

È necessario aggiungere due nuove colonne a ciascun dataset: training e test. A tale scopo, si crea una funzione per calcolare il termine di interazione e un'altra per calcolare il termine di interazione tripla. Ciascuna funzione produce una singola colonna. Dopo aver creato le nuove variabili, è possibile concatenarle al dataset di training e al dataset di test.

Prima di tutto è necessario creare una nuova variabile per l’interazione tra INDUS e NOX.

La funzione seguente restituisce due dataframe, train e test, con l'interazione tra var_1 e var_2, nel tuo caso INDUS e NOX.

def interaction_term(var_1, var_2, name):
    t_train = df_train_scale[var_1]*df_train_scale[var_2]
    train = t_train.rename(name)
    t_test = df_test_scale[var_1]*df_test_scale[var_2]
    test = t_test.rename(name)
    return train, test

Memorizzi le due nuove colonne

interation_ind_ns_train, interation_ind_ns_test= interaction_term('INDUS', 'NOX', 'INDUS_NOS')
interation_ind_ns_train.shape
(325,)

In secondo luogo, crei una seconda funzione per calcolare il termine della tripla interazione.

def triple_interaction_term(var_1, var_2,var_3, name):
    t_train = df_train_scale[var_1]*df_train_scale[var_2]*df_train_scale[var_3]
    train = t_train.rename(name)
    t_test = df_test_scale[var_1]*df_test_scale[var_2]*df_test_scale[var_3]
    test = t_test.rename(name)
    return train, test
interation_ind_ns_dis_train, interation_ind_ns_dis_test= triple_interaction_term('INDUS', 'NOX', 'DIS','INDUS_NOS_DIS')

Ora che hai tutte le colonne necessarie, puoi aggiungerle al training e al test del set di dati. Dai un nome a questi due nuovi dataframe:

  • df_train_new
  • df_test_nuovo
df_train_new = pd.concat([df_train_scale,
                          interation_ind_ns_train,
                          interation_ind_ns_dis_train],
                         axis=1, join='inner')
df_test_new = pd.concat([df_test_scale,
                         interation_ind_ns_test,
                         interation_ind_ns_dis_test],
                         axis=1, join='inner')
df_train_new.head(5)

Uscita

DataFrame di addestramento con le colonne INDUS_NOS e INDUS_NOS_DIS aggiunte.

Ecco fatto: puoi stimare il nuovo modello con i termini di interazione e vedere come si comporta in termini di prestazioni.

CONTI_FEATURES_NEW  = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT',
                       'INDUS_NOS', 'INDUS_NOS_DIS']
### Define categorical list
continuous_features_new = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES_NEW]
model = tf.estimator.LinearRegressor(
    model_dir="train_Boston_1", 
    feature_columns= categorical_features + continuous_features_new)

Uscita

INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'train_Boston_1', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x1a1a5d5860>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

Code

FEATURES = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT','INDUS_NOS', 'INDUS_NOS_DIS','CHAS']
LABEL= 'PRICE'
def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True):
    return tf.estimator.inputs.pandas_input_fn(
       x=pd.DataFrame({k: data_set[k].values for k in FEATURES}),
       y = pd.Series(data_set[LABEL].values),
       batch_size=n_batch,   
       num_epochs=num_epochs,
       shuffle=shuffle)
model.train(input_fn=get_input_fn(df_train_new, 
                                      num_epochs=None,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)

Uscita

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 1 into train_Boston_1/model.ckpt.
INFO:tensorflow:loss = 56417.703, step = 1
INFO:tensorflow:global_step/sec: 124.844
INFO:tensorflow:loss = 65522.3, step = 101 (0.803 sec)
INFO:tensorflow:global_step/sec: 182.704
INFO:tensorflow:loss = 15384.148, step = 201 (0.549 sec)
INFO:tensorflow:global_step/sec: 208.189
INFO:tensorflow:loss = 22020.305, step = 301 (0.482 sec)
INFO:tensorflow:global_step/sec: 213.855
INFO:tensorflow:loss = 28208.812, step = 401 (0.468 sec)
INFO:tensorflow:global_step/sec: 209.758
INFO:tensorflow:loss = 7606.877, step = 501 (0.473 sec)
INFO:tensorflow:global_step/sec: 196.618
INFO:tensorflow:loss = 26679.76, step = 601 (0.514 sec)
INFO:tensorflow:global_step/sec: 196.472
INFO:tensorflow:loss = 11377.163, step = 701 (0.504 sec)
INFO:tensorflow:global_step/sec: 172.82
INFO:tensorflow:loss = 8592.07, step = 801 (0.578 sec)
INFO:tensorflow:global_step/sec: 168.916
INFO:tensorflow:loss = 19878.56, step = 901 (0.592 sec)
INFO:tensorflow:Saving checkpoints for 1000 into train_Boston_1/model.ckpt.
INFO:tensorflow:Loss for final step: 19598.387.


<tensorflow.python.estimator.canned.linear.LinearRegressor at 0x1a1a5d5e10>
model.evaluate(input_fn=get_input_fn(df_test_new, 
                                      num_epochs=1,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)

Uscita

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-05-29-02:41:14
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train_Boston_1/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Finished evaluation at 2018-05-29-02:41:14
INFO:tensorflow:Saving dict for global step 1000: average_loss = 79.78876, global_step = 1000, loss = 1515.9863


{'average_loss': 79.78876, 'global_step': 1000, 'loss': 1515.9863}

La nuova perdita è 1515.9863. Semplicemente aggiungendo due nuove variabili, sei riuscito a diminuire la perdita. Significa che puoi fare una previsione migliore rispetto al modello di riferimento.

Modello Set di funzionalità Elenco dei modelli perdita_media spento
Segno di riferimento 12 colonne continue standardizzate più CHAS treno_Boston 86.89361 1650.9785
Con interazione Benchmark più INDUS_NOS e INDUS_NOS_DIS train_Boston_1 79.78876 1515.9863

Entrambi i valori provengono dalla stessa suddivisione del test di 101 righe, quindi il calo di circa l'8% nella perdita media è attribuibile esclusivamente alle due colonne di interazione.

DOMANDE FREQUENTI

È stato deprecato in scikit-learn 1.0 e rimosso nella versione 1.2. Il dataset contiene una caratteristica basata su un'ipotesi di autosegregazione razziale e prezzi delle case, e lo studio originale non ha mai convalidato la sua premessa sulla qualità dell'aria. Le abitazioni della California o di Ames sono i soliti sostituti.

Un termine polinomiale eleva al quadrato o al cubo una variabile per curvare la propria curva. Un'interazione moltiplica due variabili diverse, quindi la pendenza di una dipende dal livello dell'altra. Questo tutorial costruisce il secondo tipo, INDUS per NOX.

Cerca coppie che siano correlate tra loro e con l'obiettivo. La mappa di calore di Pearson e la griglia di coppie lo fanno visivamente; qui INDUS e NOX si raggruppano insieme ed entrambi track PREZZO, che è il segnale che giustifica il loro attraversamento.

Le librerie automatizzate di feature engineering generano trasformazioni e incroci candidati, li valutano confrontandoli con un set di test e mantengono solo quelli che riducono l'errore. Questo sostituisce la lettura manuale della mappa di calore mostrata qui, sebbene sia comunque necessario un controllo umano per interpretare correttamente le colonne generate.

Copilot gestisce bene le operazioni ripetitive di creazione di grafici, come griglie a coppie, mappe di calore mascherate e modelli HTML per le faccette. Controlla gli argomenti che suggerisce, perché seaborn ne ha rinominati diversi e Copilot non ha problemi a combinare firme vecchie e nuove.

No. La perdita deve essere confrontata sulla stessa suddivisione dei dati di test, come in questo caso. Una perdita che si verifica solo sui dati di training segnala overfitting, e l'aggiunta di colonne migliora quasi sempre l'adattamento del training, indipendentemente dal fatto che contengano o meno informazioni reali.

La maschera utilizza np.bool, un alias deprecato in NumPy 1.20 e rimosso nella versione 1.24. Le installazioni recenti generano un AttributeError. Sostituendolo con il tipo bool integrato, il comportamento rimane identico; anche np.bool_ funziona se è necessario il tipo scalare di NumPy.

CHAS è un flag categoriale sì/no e PRICE è l'etichetta. Centrare e scalare una variabile dummy rende più difficile la lettura del suo coefficiente senza modificare l'adattamento, e scalare l'etichetta riscalarerebbe semplicemente la perdita riportata. Solo i dodici predittori continui sono standardizzati.

Riassumi questo post con: