TensorFlow linjär regression med facett & interaktionsterm
⚡ Smart sammanfattning
Linjär regression på bostadsdata från Boston förbättras när rätt interaktionstermer hittas först. Google Facetter exponerar dessa relationer visuellt, och två korsade funktioner minskar TensorFlow-testförlusten från 1650 till 1515.

TensorFlow linjär regression
I den här handledningen kommer du att lära dig hur du kontrollerar data och förbereder dem för att skapa en enkel linjär regressionsuppgift.
Denna handledning är uppdelad i två delar:
- Leta efter interaktion
- Testa modellen
I tidigare handledning, använde du Boston-datauppsättningen för att uppskatta medianpriset för ett hus. Boston dataset har en liten storlek, med endast 506 observationer. Denna datauppsättning betraktas som ett riktmärke för att testa nya linjära regressionsalgoritmer.
Datauppsättningen består av:
| Variabel | BESKRIVNING |
|---|---|
| zn | Andelen bostadsmark som är planlagd för tomter över 25,000 XNUMX kvm. |
| indus | Andelen icke-handelsföretagare per stad. |
| nox | kväveoxidkoncentration |
| rm | genomsnittligt antal rum per bostad |
| ålder | andelen ägarlägenheter byggda före 1940 |
| DIS | vägda avstånd till fem arbetsförmedlingar i Boston |
| skatt | fastighetsskattesats för fullt värde per dollar 10,000 XNUMX |
| ptratio | förhållandet elev-lärare av en stad |
| medv | Medianvärdet för ägda bostäder i tusen dollar |
| krim | brottslighet per capita per stad |
| Chas | Charles River dummyvariabel (1 om gränsen till floden; 0 annars) |
| B | andelen svarta vid staden |
I den här handledningen kommer vi att uppskatta medianpriset med hjälp av en linjär regressor, men fokus ligger på en speciell process av maskininlärning: "dataförberedelse."
En modell generaliserar mönstret i datan. För att fånga ett sådant mönster måste du hitta det först. En bra praxis är att utföra en dataanalys innan du kör någon maskininlärningsalgoritm.
Att välja rätt funktioner gör stor skillnad för din modells framgång. Föreställ dig att du försöker uppskatta lönen för ett folk, om du inte tar med könet som en samvariat så hamnar du på en dålig uppskattning.
Ett annat sätt att förbättra modellen är att titta på korrelationen mellan den oberoende variabeln. Tillbaka till exemplet, du kan tänka dig utbildning som en utmärkt kandidat för att förutsäga lönen men också yrket. Det är rimligt att säga att yrket beror på utbildningsnivån, nämligen högre utbildning leder ofta till ett bättre yrke. Om vi generaliserar denna idé kan vi säga att korrelationen mellan den beroende variabeln och en förklaringsvariabel kan förstoras med ännu en förklaringsvariabel.
För att fånga utbildningens begränsade effekt på yrket kan vi använda en interaktionsterm.
Om man tittar på löneekvationen blir den:
If är positivt, så innebär det att en extra utbildningsnivå ger en högre ökning av medianvärdet på ett hus för en hög yrkesnivå. Det finns med andra ord en interaktionseffekt mellan utbildning och yrke.
Samma estimatorfamilj driver också linjär klassificerare när etiketten är en klass snarare än ett pris. I den här handledningen ska vi försöka se vilka variabler som kan vara en bra kandidat för interaktionstermer. Vi ska testa om att lägga till den här typen av information leder till bättre prisförutsägelser.
Sammanfattande statistik
Det finns några steg du kan följa innan du går vidare till modellen. Som tidigare nämnts är modellen en generalisering av data. Det bästa är att först förstå data och sedan göra en förutsägelse. Om du inte känner till dina data har du små chanser att förbättra din modell.
Som ett första steg, ladda data som en pandas dataram och skapa ett träningsset och testset.
Tips: För den här handledningen behöver du ha matplotlib och seaborn installerade i PythonDu kan installera en Python paket i farten med Jupyter. Ni Borde inte gör det här
!conda install -- yes matplotlib
men
import sys !{sys.executable} -m pip install matplotlib # Already installed !{sys.executable} -m pip install seaborn
Observera att detta steg inte är nödvändigt om du har matplotlib och seaborn installerat.
Matplotlib är biblioteket att skapa en graf i PythonSeaborn är ett statistiskt visualiseringsbibliotek byggt ovanpå matplotlib. Det tillhandahåller bland annattractiv och vackra intriger.
Koden nedan importerar de nödvändiga biblioteken.
import pandas as pd from sklearn import datasets import tensorflow as tf from sklearn.datasets import load_boston import numpy as np
Biblioteket sklearn inkluderar Boston dataset. Du kan anropa dess API för att importera data.
Versionsnotering: load_boston blev föråldrad i scikit-learn 1.0 och borttagen i scikit-learn 1.2 eftersom datamängden kodar för en rasistiskt laddad funktion. Använd på en aktuell installation fetch_california_housing istället, eller ladda råfilen själv. Arbetsflödet som visas nedan är oförändrat; endast laddaren skiljer sig.
boston = load_boston() df = pd.DataFrame(boston.data)
Funktionsnamnen lagras i objektet feature_names som en array.
boston.feature_names
Produktion
array(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT'], dtype='<U7')
Du kan byta namn på kolumnerna.
df.columns = boston.feature_names
df['PRICE'] = boston.target
df.head(2)
Du konverterar variabeln CHAS till en strängvariabel och märker den med ja om CHAS = 1 och nej om 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
Med pandor är det enkelt att dela upp datasetet. Du delar upp datasetet slumpmässigt med 80 procent träningsuppsättning och 20 procent testsats. pandas har en inbyggd samplingsfunktion för att dela en dataram.
Den första parametern frac är ett värde från 0 till 1. Du ställer in det på 0.8 för att slumpmässigt välja 80 procent av dataramen.
random_state fixar blandningen, så samma rader returneras för alla.
### Create train/test set
df_train=df.sample(frac=0.8,random_state=200)
df_test=df.drop(df_train.index)
Du kan få formen på datan. Det borde vara:
- Tågsats: 506*0.8 = 405
- Testuppsättning: 506*0.2 = 101
print(df_train.shape, df_test.shape)
Produktion
(405, 14) (101, 14)
df_test.head(5)
Produktion
| CRIM | ZN | INDUS | CHAS | NOX | RM | ÅLDER | DIS | RAD | sKATT | PTRATIO | B | LSTAT | PRIS | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.00632 | 18.0 | 2.31 | Nej | 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 | Nej | 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 | Nej | 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 | Nej | 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 | Nej | 0.524 | 6.172 | 96.1 | 5.9505 | 5.0 | 311.0 | 15.2 | 396.90 | 19.15 | 27.1 |
Data är rörigt; den är ofta felbalanserad och beströdd med extremvärden som kastar bort analysen och maskininlärningsträningen.
Det första steget för att få datauppsättningen ren är att förstå var den behöver rengöras. Att rensa upp en datauppsättning kan vara knepigt att göra, särskilt på alla generaliserbara sätt
Ocuco-landskapet Google Forskargruppen har utvecklat ett verktyg för detta arbete som kallas fasetter som hjälper dig att visualisera data och dela upp dem på alla möjliga sätt. Detta är en bra utgångspunkt för att förstå hur datamängden är upplagd.
Med fasetter kan du hitta var informationen inte riktigt ser ut som du förväntar dig.
Förutom deras webbapp, Google gör det enkelt att bädda in verktygslådan i en Jupyter anteckningsbok.
Det finns två delar till Facets:
- Fasettöversikt
- Facetter Deep Dive
Fasettöversikt
Facets Overview ger en översikt över datamängden. Fasettöversikt delar upp kolumnerna med data i rader med framträdande information som visas
- procentandelen saknade observationer
- min och max värden
- statistik som medelvärde, median och standardavvikelse.
- Den lägger också till en kolumn som visar procentandelen värden som är nollor, vilket är användbart när de flesta värdena är nollor.
- Det är möjligt att se dessa distributioner på testdatauppsättningen såväl som träningsuppsättningen för varje funktion. Det betyder att du kan dubbelkolla att testet har en liknande fördelning som träningsdata.
Detta är åtminstone det minsta att göra innan någon maskininlärningsuppgift. Med det här verktyget missar du inte detta avgörande steg, och det lyfter fram några avvikelser.
Facetter Deep Dive
Facets Deep Dive är ett coolt verktyg. Det låter dig få lite klarhet i din datauppsättning och zooma in helt för att se en enskild dataenhet. Det betyder att du kan fasettera data rad- och kolumnvis över alla funktioner i datauppsättningen.
Vi kommer att använda dessa två verktyg med Boston dataset.
Anmärkningar: Du kan inte använda Facets Overview och Facets Deep Dive samtidigt. Du måste rensa anteckningsboken först för att byta verktyg.
Innan något av verktygen kan användas måste Facets installeras i den bärbara datormiljön.
Installera Facet
Du kan använda Facet-webbappen för det mesta av analysen. I den här handledningen kommer du att se hur du använder den inom en Jupyter Anteckningsbok.
Först och främst måste du installera nbextensions. Det görs med denna kod. Du kopierar och klistrar in följande kod i terminalen på din maskin.
pip install jupyter_contrib_nbextensions
Direkt efter det måste du klona arkiven i din dator. Du har två val:
Alternativ 1) Kopiera och klistra in denna kod i terminalen (Rekommenderas)
Om du inte har Git installerat på din maskin, gå till den här sidan URL Git för Windows ladda sidan och följ instruktionerna. När du är klar kan du använda git-kommandot i terminalen för Mac-användare eller Anaconda-prompten för Windows användare
git clone https://github.com/PAIR-code/facets
Alternativ 2) Gå till PAIR-kod/aspektförrådet och ladda ner arkiven.
Sidan ovan innehåller nedladdningsknappen som används av alternativ 2. Om du väljer det första alternativet hamnar filen i din nedladdningsmapp. Du kan antingen låta filen laddas ner eller dra den till en annan sökväg.
Du kan kontrollera var Facets lagras med den här kommandoraden:
echo `pwd`/`ls facets`
Nu när du har hittat Facets måste du installera den i Jupyter Anteckningsbok. Du måste ställa in arbetskatalogen till sökvägen där fasetter finns.
Din nuvarande arbetskatalog och plats för Facets zip bör vara samma.
Terminallistan ovan bekräftar att facets finns i den aktuella arbetskatalogen. Du måste peka arbetskatalogen till Facet:
cd facets
För att installera Facets i Jupyter, du har två alternativ. Om du har installerat Jupyter med Conda för alla användare, kopiera denna kod:
jupyter nbextension install facets-dist/
Använd annars:
jupyter nbextension install facets-dist/ --user
Okej, du är klar. Låt oss öppna Facet Overview.
Översikt över köra fasetter i Jupyter
Översikt använder en Python skript för att beräkna statistiken. Du måste importera skriptet som heter generic_feature_statistics_generator till Jupyter. Oroa dig inte; skriptet finns i facettfilerna.
Du måste hitta dess väg. Det är lätt gjort. Du öppnar facets, öppnar filen facets_overview och sedan python. Kopiera sökvägen
Efter det, gå tillbaka till Jupyter, och skriv följande kod. Ändra sökvägen '/Users/Thomas/facets/facets_overview/python' till din sökväg.
# Add the facets overview python code to the python path# Add t import sys sys.path.append('/Users/Thomas/facets/facets_overview/python')
Du kan importera skriptet med koden nedan.
from generic_feature_statistics_generator import GenericFeatureStatisticsGenerator
I windows blir samma kod
import sys sys.path.append(r"C:\Users\Admin\Anaconda3\facets-master\facets_overview\python") from generic_feature_statistics_generator import GenericFeatureStatisticsGenerator
För att beräkna funktionsstatistiken måste du använda funktionen GenericFeatureStatisticsGenerator(), och du använder objektet ProtoFromDataFrames. Du kan skicka dataramen i en ordbok. Om vi till exempel vill skapa en sammanfattande statistik för tåguppsättningen kan vi lagra informationen i en ordbok och använda den i objektet `ProtoFromDataFrames“
'name': 'train', 'table': df_train
Namn är namnet på tabellen som visas, och du använder namnet på tabellen som du vill beräkna sammanfattningen. I ditt exempel är tabellen som innehåller data 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")
Till sist kopierar och klistrar du bara in koden nedan. Koden kommer direkt från GitHub. Du borde kunna se detta:
# 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))
Korrelationsgraf och parrutnät
När du har kontrollerat data och deras fördelning kan du plotta en korrelationsmatris. Korrelationsmatrisen beräknar Pearson-koefficienten. Denna koefficient är begränsad mellan -1 och 1, där ett positivt värde indikerar en positiv korrelation och ett negativt värde en negativ korrelation.
Du är intresserad av att se vilka variabler som kan vara en bra kandidat för interaktionstermer.
Versionsnotering: masken nedan kallar np.bool, ett alias som avregistrerades i NumPy 1.20 och borttagen i NumPy 1.24På en nyligen genomförd NumPy höjs samma linje AttributeError: module 'numpy' has no attribute 'bool'den inbyggda bool är drop-in-ersättningen.
## 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})
Produktion
<matplotlib.axes._subplots.AxesSubplot at 0x1a184d6518>
I värmekartan ovan markerar mörkare rutor starkare korrelationer. Från matrisen kan du se:
- LSTAT
- RM
Är starkt korrelerade med PRICE. En annan spännande egenskap är den starka positiva korrelationen mellan NOX och INDUS, vilket innebär att dessa två variabler rör sig i samma riktning. Båda är också korrelerade med PRICE. DIS är också starkt korrelerad med INDUS och NOX.
Du har en första antydan om att INDUS och NOX kan vara bra kandidater för en interaktionsterm och att DIS också kan vara intressant att fokusera på.
Du kan gå lite djupare genom att rita ett parrutnät. Det kommer att illustrera mer i detalj korrelationskartan du ritade tidigare.
Parnätet är uppbyggt enligt följande:
- Övre del: Spridningstomt med inpassad linje
- Diagonal: Kärndensitetsdiagram
- Nedre del: Multivariat kärndensitetsdiagram
Du fokuserar på fyra oberoende variabler. Valet motsvarar de variabler med stark korrelation med PRICE
- INDUS
- NOX
- RM
- LSTAT
dessutom PRIS.
Anmärkningar att standardfelet läggs till som standard till spridningsdiagrammet.
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)
Produktion
Låt oss börja med den övre delen:
- Priset är negativt korrelerat med INDUS, NOX och LSTAT; positivt korrelerad med RM.
- Det finns en viss icke-linjäritet mellan LSTAT och PRICE
- Det finns som en rät linje när priset är lika med 50. Från beskrivningen av datasetet har PRICE trunkerats till värdet 50
Diagonal: NOX verkar ha två kluster, ett runt 0.5 och ett runt 0.85.
För att kolla mer om det kan du titta på den nedre delen. Den multivariata kärndensiteten är intressant i en mening den färgar där de flesta punkterna finns. Skillnaden med spridningsdiagrammet ritar en sannolikhetstäthet, även om det inte finns någon poäng i datasetet för en given koordinat. När färgen är starkare indikerar det en hög koncentration av punkt runt detta område.
Om du kontrollerar den multivariata densiteten för INDUS och NOX kan du se den positiva korrelationen och de två klustren. När industrins andel är över 18 är kväveoxidkoncentrationen över 0.6.
Du kan tänka på att lägga till en interaktion mellan INDUS och NOX i det linjära förhållandet.
Slutligen kan du använda det andra verktyget som skapats av Google, Djupgående analyser av fasetter. Gränssnittet är uppdelat i fyra huvudavsnitt. Det centrala området i mitten är en zoombar visning av data. Högst upp på panelen finns en rullgardinsmeny där du kan ändra arrangemanget av data för att kontrollera fasettering, positionering och färg. Till höger finns en detaljerad vy av en specifik datarad. Det betyder att du kan klicka på valfri datapunkt i den mittersta visualiseringen för att se detaljer om just den datapunkten.
Under datavisualiseringssteget är du intresserad av att leta efter den parvisa korrelationen mellan den oberoende variabeln på husets pris. Det involverar dock minst tre variabler och 3D-plots är komplicerade att arbeta med.
Ett sätt att ta itu med detta problem är att skapa en kategorisk variabel. Det vill säga att vi kan skapa ett 2D-diagram och färglägga punkterna. Du kan dela upp variabeln PRICE i fyra kategorier, där varje kategori är en kvartil (dvs. 0.25, 0.5, 0.75). Du kallar denna nya variabel Q_PRICE.
## 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")
Använda djupdykning i fasetter
För att öppna Deep Dive måste du omvandla data till ett json-format. Pandas har en metod för det: anropa to_json på DataFrame.
Den första raden kod anger spritens storlek beroende på hur många rader datamängden innehåller.
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')
Koden nedan kommer från Google GitHub. När du har kört koden bör du kunna se detta:
# 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))
Du är intresserad av att se om det finns ett samband mellan branschtakt, oxidkoncentration, avstånd till arbetsförmedlingen och priset på huset.
För det delar du först upp data efter branschintervall och färg med priskvartilen:
- Välj facettering X och välj INDUS.
- Välj Display och välj DIS. Det kommer att färga prickarna med kvartilen av huspriset
Här betyder mörkare färger att avståndet till det första arbetsförmedlingen är större.
Än så länge visar det igen vad du vet, lägre industripris, högre pris. Nu kan du titta på fördelningen av INDUX, efter NOX.
Välj facettering Y och välj NOX.
Nu kan man se att huset långt ifrån den första arbetsförmedlingen har lägst industriandel och därmed lägst oxidkoncentration. Om du väljer att visa typen med Q_PRICE och zooma ner i det nedre vänstra hörnet kan du se vilken typ av pris det är.
Du har ytterligare en hint om att interaktionen mellan IND, NOX och DIS kan vara bra kandidater för att förbättra modellen.
Utforskningen har producerat två potentiella interaktioner, så nästa steg är att testa dem i en faktisk modell.
Linjär regression med TensorFlow
I det här avsnittet ska du uppskatta den linjära regressionsmodellen med TensorFlow Estimator API. Du fortsätter enligt följande:
- Förbered data
- Uppskatta en benchmarkmodell: Ingen interaktion
- Uppskatta en modell med interaktion
Versionsnotering: d tf-estimator paketet levererades i sin slutliga utgåva med TensorFlow 2.15 och saknas från TensorFlow 2.16 och framåt, så tf.estimator.LinearRegressor körs bara på TensorFlow 1.x om du inte migrerar det till en Keras linjär modell.
Kom ihåg att målet med maskininlärning är att minimera felet. I det här fallet vinner modellen med det lägsta medelkvadratfelet. TensorFlow-estimatorn beräknar automatiskt detta mått.
Beredningsdata
I de flesta fall behöver du omvandla dina data. Det är därför Facets Overview är fascinerande. Från den sammanfattande statistiken såg du att det finns extremvärden. Dessa värden påverkar uppskattningarna eftersom de inte ser ut som den population du analyserar. Extremvärden snedvrider vanligtvis resultaten. Till exempel tenderar ett positivt extremvärde att överskatta koefficienten.
En bra lösning för att ta itu med detta problem är att standardisera variabeln. Standardisering innebär en standardavvikelse på ett och ett medelvärde på noll. Standardiseringsprocessen involverar två steg. Först och främst, den subtracts medelvärdet av variabeln. För det andra dividerar den med standardavvikelsen så att fördelningen har en enhetsstandardavvikelse.
Biblioteket scikit lära är användbart för att standardisera variabler. Du kan använda modulens förbehandling med objektskalningen för detta ändamål.
Du kan använda funktionen nedan för att skala en datauppsättning. Observera att du inte skalar etikettkolumnen och kategoriska variabler.
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
Du kan använda funktionen för att konstruera det skalade tåget/testsetet.
df_train_scale = standardize_data(df_train) df_test_scale = standardize_data(df_test)
Grundläggande regression: Benchmark
Först och främst tränar och testar du en modell utan interaktion. Syftet är att se modellens prestandamått.
Sättet att träna modellen är exakt som i handledningen på API på hög nivå. Du kommer att använda TensorFlow-estimatorn LinearRegressor.
Som en påminnelse måste du välja:
- funktionerna att sätta i modellen
- förvandla funktionerna
- konstruera den linjära regressorn
- konstruera funktionen input_fn
- träna modellen
- testa modellen
Du använder alla variabler i datamängden för att träna modellen. Totalt finns det tolv kontinuerliga variabler och en kategorisk variabel.
## 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']
Du konverterar funktionerna till en numerisk kolumn eller kategorisk kolumn
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'])]
Du skapar modellen med linearRegressor. Du lagrar modellen i mappen train_Boston
model = tf.estimator.LinearRegressor(
model_dir="train_Boston",
feature_columns=categorical_features + continuous_features)
Produktion
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}
Varje kolumn i tåget eller testdatan konverteras till en tensor med funktionen 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)
Du uppskattar modellen på tågdata.
model.train(input_fn=get_input_fn(df_train_scale,
num_epochs=None,
n_batch = 128,
shuffle=False),
steps=1000)
Produktion
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>
Till sist uppskattar du modellens prestanda på testsetet
model.evaluate(input_fn=get_input_fn(df_test_scale,
num_epochs=1,
n_batch = 128,
shuffle=False),
steps=1000)
Produktion
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}
Förlusten av modellen är 1650.9785. Detta är måtten att slå i nästa avsnitt
Förbättra modellen: Interaktionsterm
Under den första delen av handledningen såg du ett intressant samband mellan variablerna. De olika visualiseringsteknikerna visade att INDUS och NOX är kopplade till varandra och förstärker varandras effekt på priset. Samspelet mellan INDUS och NOX påverkar inte bara priset, utan denna effekt är också starkare när det interagerar med DIS.
Det är dags att generalisera denna idé och se om man kan förbättra modellprediktionen.
Du behöver lägga till två nya kolumner till varje dataset: train och test. För det skapar du en funktion för att beräkna interaktionstermen och en annan för att beräkna den tredubbla interaktionstermen. Varje funktion producerar en enda kolumn. När de nya variablerna har skapats kan du sammanfoga dem med träningsdatasetet och testdatasetet.
Först och främst måste du skapa en ny variabel för interaktionen mellan INDUS och NOX.
Funktionen nedan returnerar två dataramar, träna och testa, med interaktionen mellan var_1 och var_2, i ditt fall INDUS och 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
Du lagrar de två nya kolumnerna
interation_ind_ns_train, interation_ind_ns_test= interaction_term('INDUS', 'NOX', 'INDUS_NOS') interation_ind_ns_train.shape (325,)
För det andra skapar du en andra funktion för att beräkna trippelinteraktionstermen.
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')
Nu när du har alla kolumner som behövs kan du lägga till dem för att träna och testa dataset. Du namnger dessa två nya dataramar:
- df_train_new
- df_test_new
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)
Produktion
Det är allt: du kan uppskatta den nya modellen med interaktionstermerna och se hur prestandametriken är.
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)
Produktion
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)
Produktion
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)
Produktion
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}
Den nya förlusten är 1515.9863. Bara genom att lägga till två nya variabler kunde du minska förlusten. Det betyder att du kan göra en bättre förutsägelse än med benchmarkmodellen.
| Modell | Funktionsuppsättning | Modellkatalog | genomsnittlig_förlust | förlust |
|---|---|---|---|---|
| riktmärke | 12 standardiserade kontinuerliga kolumner plus CHAS | tåg_Boston | 86.89361 | 1650.9785 |
| Med interaktion | Riktmärke plus INDUS_NOS och INDUS_NOS_DIS | tåg_Boston_1 | 79.78876 | 1515.9863 |
Båda siffrorna kommer från samma testdelning på 101 rader, så minskningen på ungefär 8 procent i genomsnittlig förlust kan enbart tillskrivas de två interaktionskolumnerna.











