TensorFlow lineær regression med facet- og interaktionsterm

⚡ Smart opsummering

Lineær regression på boligdataene fra Boston forbedres, når de rigtige interaktionstermer findes først. Google Facetter eksponerer disse relationer visuelt, og to krydsede funktioner reducerede TensorFlow-testtabet fra 1650 til 1515.

  • 🔘 Data først: Forståelse af fordelinger og outliers går forud for enhver model, fordi en model kun generaliserer et mønster, du allerede har fundet.
  • ☑️ Oversigt over facetter: Statistikker pr. funktion viser manglende værdier, kolonner med et lavt indhold af nul og forskydning af tog-versus-test-fordelingen i én tabel.
  • Dybdegående facetter: Facettering med X og Y omdanner trevejsrelationer til et læsbart 2D-plot farvet efter priskvartil.
  • 🧪 Korrelationslæsning: Varmekortet og pargitteret markerer INDUS med NOX og DIS med begge som interaktionskandidater.
  • 🛠️ Standardisering: preprocessing.scale centrerer de tolv kontinuerlige kolonner, før estimatoren ser dem, hvilket lader CHAS og PRICE være uberørte.
  • 📈 Målt forstærkning: Ved at lægge INDUS_NOS og INDUS_NOS_DIS sammen, flyttes det gennemsnitlige tab fra 86.89361 til 79.78876 på testopdelingen.

TensorFlow lineær regression med facet- og interaktionsterm

TensorFlow lineær regression

I denne øvelse lærer du, hvordan du kontrollerer dataene og forbereder dem til at lave en simpel lineær regressionsopgave.

Denne tutorial er opdelt i to dele:

  • Se efter interaktion
  • Test modellen

I tidligere vejledning, brugte du Boston-datasættet til at estimere medianprisen for et hus. Boston-datasættet har en lille størrelse med kun 506 observationer. Dette datasæt betragtes som et benchmark for at prøve nye lineære regressionsalgoritmer.

Datasættet er sammensat af:

Variabel Beskrivelse
zn Andelen af ​​boligarealer udlagt til grunde over 25,000 kvm.
indu Andelen af ​​ikke-detailvirksomheder pr. by.
nox koncentration af nitrogenoxider
rm gennemsnitligt antal værelser pr. bolig
alder andelen af ​​ejerlejligheder bygget før 1940
dis vægtede afstande til fem Boston beskæftigelsescentre
skat ejendomsskattesats for fuld værdi pr. dollars 10,000
ptratio elev-lærer-forholdet i en by
medv Medianværdien af ​​ejerboliger i tusinde dollars
kriminel kriminalitet pr. indbygger efter by
Chas Charles River dummy-variabel (1 hvis grænser til floden; ellers 0)
B andelen af ​​sorte i byen

I denne vejledning vil vi estimere medianprisen ved hjælp af en lineær regressor, men fokus er på en bestemt proces med machine learning: "dataforberedelse."

En model generaliserer mønstret i dataene. For at fange et sådant mønster skal du først finde det. En god praksis er at udføre en dataanalyse, før du kører nogen maskinlæringsalgoritme.

At vælge de rigtige funktioner gør hele forskellen for din models succes. Forestil dig, at du forsøger at estimere et folks løn, hvis du ikke inkluderer kønnet som en kovariat, ender du med et dårligt skøn.

En anden måde at forbedre modellen på er at se på sammenhængen mellem den uafhængige variabel. Tilbage til eksemplet kan du tænke på uddannelse som en fremragende kandidat til at forudsige lønnen, men også erhvervet. Det er rimeligt at sige, at erhvervet afhænger af uddannelsesniveauet, nemlig videregående uddannelse fører ofte til et bedre erhverv. Hvis vi generaliserer denne idé, kan vi sige, at korrelationen mellem den afhængige variabel og en forklarende variabel kan forstørres af endnu en forklarende variabel.

For at fange uddannelsens begrænsede effekt på erhverv kan vi bruge et interaktionsbegreb.

Interaktionsbegreb mellem uddannelse og erhverv illustreret på en lønkurve

Hvis du ser på lønligningen, bliver den:

Lønligningen udvidet med et interaktionsled for uddannelse ganget med erhverv

If Betakoefficientsymbol for interaktionstermen er positivt, så indebærer det, at et ekstra uddannelsesniveau giver en højere stigning i medianværdien af ​​et hus for et højt besættelsesniveau. Der er med andre ord en vekselvirkning mellem uddannelse og erhverv.

Den samme estimatorfamilie driver også lineær klassifikator når etiketten er en klasse snarere end en pris. I denne vejledning vil vi forsøge at se, hvilke variabler der kan være en god kandidat til interaktionstermer. Vi vil teste, om tilføjelse af denne type information fører til bedre prisforudsigelser.

Sammenfattende statistik

Der er et par trin, du kan følge, før du går videre til modellen. Som tidligere nævnt er modellen en generalisering af dataene. Den bedste praksis er først at forstå dataene og derefter lave en forudsigelse. Hvis du ikke kender dine data, har du små chancer for at forbedre din model.

Som et første trin skal du indlæse dataene som en panda-dataramme og oprette et træningssæt og testsæt.

Tips: Til denne vejledning skal du have matplotlib og seaborn installeret i PythonDu kan installere en Python pakke i farten med Jupyter. Du Burde ikke gør dette

!conda install -- yes matplotlib

men

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

Bemærk, at dette trin ikke er nødvendigt, hvis du har installeret matplotlib og seaborn.

Matplotlib er biblioteket til at lave en graf i PythonSeaborn er et statistisk visualiseringsbibliotek bygget oven på matplotlib. Det tilbyder følgende:tractive og smukke plots.

Koden nedenfor importerer de nødvendige biblioteker.

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

Biblioteket sklearn inkluderer Boston-datasættet. Du kan kalde dens API for at importere dataene.

Versionsnotat: load_boston blev udfaset i scikit-learn 1.0 og fjernet i scikit-learn 1.2 fordi datasættet koder en racemæssigt ladet funktion. Brug på en aktuel installation fetch_california_boliger eller indlæs råfilen selv. Arbejdsgangen vist nedenfor er uændret; kun indlæseren er anderledes.

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

Funktionsnavnene gemmes i objektet feature_names som et array.

boston.feature_names

Produktion

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

Du kan omdøbe kolonnerne.

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

De første to rækker af Boston DataFrame efter omdøbning af kolonnerne

Du konverterer variablen CHAS som en strengvariabel og mærker den med ja hvis CHAS = 1 og nej hvis 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 pandaer er det ligetil at opdele datasættet. Du opdeler tilfældigt datasættet med 80 procent træningssæt og 20 procent testsæt. pandas har en indbygget samplingfunktion til at opdele en dataramme.

Den første parameter frac er en værdi fra 0 til 1. Du indstiller den til 0.8 for at vælge tilfældigt 80 procent af datarammen.

random_state retter blandningen, så de samme rækker returneres for alle.

### 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å dataene. Det bør være:

  • Togsæt: 506*0.8 = 405
  • Testsæt: 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 ALDER DIS RAD SKAT PTRATIO B LSTAT PRIS
0 0.00632 18.0 2.31 ingen 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 ingen 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 ingen 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 ingen 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 ingen 0.524 6.172 96.1 5.9505 5.0 311.0 15.2 396.90 19.15 27.1

Data er rodet; det er ofte misbalanceret og overstrøet med afvigende værdier, der afslører analyse- og maskinlæringstræningen.

Det første skridt til at få ryddet op i datasættet er at forstå, hvor det skal renses. Det kan være vanskeligt at rydde op i et datasæt, især på enhver generaliserbar måde

Google Forskerholdet har udviklet et værktøj til dette job kaldet facetter der hjælper dig med at visualisere dataene og opdele dem på alle mulige måder. Dette er et godt udgangspunkt for at forstå, hvordan datasættet er opbygget.

Med Facetter kan du finde ud af, hvor dataene ikke helt ser ud, som du forventer.

Bortset fra deres webapp, Google gør det nemt at integrere værktøjssættet i en Jupyter notesbog.

Der er to dele til Facetter:

  • Oversigt over facetter
  • Facetter Deep Dive

Oversigt over facetter

Oversigt over facetter giver et overblik over datasættet. Oversigt over facetter opdeler kolonnerne med dataene i rækker med fremtrædende information, der vises

  1. procentdelen af ​​manglende observation
  2. min og max værdier
  3. statistik som middelværdi, median og standardafvigelse.
  4. Det tilføjer også en kolonne, der viser procentdelen af ​​værdier, der er nuller, hvilket er nyttigt, når de fleste af værdierne er nuller.
  5. Det er muligt at se disse distributioner på testdatasættet samt træningssættet for hver funktion. Det betyder, at du kan dobbelttjekke, at testen har en lignende fordeling som træningsdataene.

Dette er i det mindste minimum at gøre før enhver maskinlæringsopgave. Med dette værktøj går du ikke glip af dette afgørende trin, og det fremhæver nogle abnormiteter.

Facetter Deep Dive

Facets Deep Dive er et smart værktøj. Det giver dig mulighed for at få mere overblik over dit datasæt og zoome helt ind for at se et individuelt datasæt. Det betyder, at du kan facettere dataene række for række på tværs af alle funktioner i datasættet.

Vi vil bruge disse to værktøjer med Boston-datasættet.

Bemærk: Du kan ikke bruge Facets Overview og Facets Deep Dive på samme tid. Du skal først rydde notesbogen for at skifte værktøj.

Før et af værktøjerne kan bruges, skal Facets installeres i den bærbare computer.

Installer Facet

Du kan bruge Facet-webappen til det meste af analysen. I denne tutorial vil du se, hvordan du bruger den inden for en Jupyter Notebook.

Først og fremmest skal du installere nbextensions. Det gøres med denne kode. Du kopierer og indsætter følgende kode i terminalen på din maskine.

pip install jupyter_contrib_nbextensions

Lige derefter skal du klone lagrene på din computer. Du har to valg:

Mulighed 1) Kopiér og indsæt denne kode i terminalen (Anbefalede)

Hvis du ikke har Git installeret på din maskine, skal du gå til dette URL Git for Windows download siden og følg instruktionen. Når du er færdig, kan du bruge git-kommandoen i terminalen til Mac-bruger eller Anaconda-prompten Windows bruger

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

Mulighed 2) Gå til PAIR-kode/facetarkivet og download arkiverne.

PAIR-kode facetlagerside på GitHub

Ovenstående arkivside indeholder downloadknappen, der bruges af mulighed 2. Hvis du vælger den første mulighed, ender filen i din downloadmappe. Du kan enten lade filen downloade eller trække den til en anden sti.

Du kan kontrollere, hvor facetter er gemt med denne kommandolinje:

echo `pwd`/`ls facets`

Nu hvor du har fundet Facets, skal du installere det i Jupyter Notesbog. Du skal indstille arbejdsmappen til stien, hvor facetter er placeret.

Din nuværende arbejdsmappe og placering af Facets zip skal være den samme.

Terminal, der viser facets-mappen i den nuværende arbejdsmappe

Terminallisten ovenfor bekræfter, at facets er placeret i den aktuelle arbejdsmappe. Du skal pege arbejdsmappen til Facet:

cd facets

For at installere Facets i Jupyter, du har to muligheder. Hvis du har installeret Jupyter med Conda for alle brugerne, kopier denne kode:

jupyter nbextension install facets-dist/

Ellers brug:

jupyter nbextension install facets-dist/ --user

Okay, du er klar. Lad os åbne Facet Oversigt.

Oversigt over kørselsfacetter i Jupyter

Oversigt bruger en Python script til at beregne statistikken. Du skal importere scriptet kaldet generic_feature_statistics_generator til Jupyter. Bare rolig; scriptet er placeret i facetfilerne.

Du skal finde dens vej. Det er nemt gjort. Du åbner facetter, åbner filen facets_overview og derefter python. Kopier stien

Filsti til facets_overview python-mappen

Gå derefter tilbage til Jupyter, og skriv følgende kode. Skift stien '/Users/Thomas/facets/facets_overview/python' til din sti.

# 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 importere scriptet med koden nedenfor.

from generic_feature_statistics_generator import 
GenericFeatureStatisticsGenerator

I windows bliver den samme kode

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

from generic_feature_statistics_generator import GenericFeatureStatisticsGenerator

For at beregne funktionsstatistikken skal du bruge funktionen GenericFeatureStatisticsGenerator(), og du bruger objektet ProtoFromDataFrames. Du kan sende datarammen i en ordbog. For eksempel, hvis vi ønsker at oprette en oversigtsstatistik for togsættet, kan vi gemme informationen i en ordbog og bruge den i objektet `ProtoFromDataFrames“

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

Navn er navnet på den tabel, der vises, og du bruger navnet på den tabel, du ønsker, til at beregne oversigten. I dit eksempel er tabellen, der indeholder dataene, 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")

Til sidst kopierer og indsætter du blot koden nedenfor. Koden kommer direkte fra GitHub. Du burde kunne se dette:

Oversigtstabel over facetter med opsummerende statistikker pr. funktion

# 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 og pargitter

Når du har kontrolleret dataene og deres fordeling, kan du plotte en korrelationsmatrix. Korrelationsmatrixen beregner Pearson-koefficienten. Denne koefficient er begrænset mellem -1 og 1, hvor en positiv værdi angiver en positiv korrelation, og en negativ værdi en negativ korrelation.

Du er interesseret i at se, hvilke variabler der kan være en god kandidat til interaktionsbegreber.

Versionsnotat: masken nedenfor kalder np.bool, et alias, der blev udfaset i NumPy 1.20 og fjernet i NumPy 1.24På en nylig NumPy hæves den samme linje AttributeError: module 'numpy' has no attribute 'bool'den indbyggede bool er drop-in-erstatningen.

## 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>

Seaborn-korrelationsvarmekort over Boston-variabler

I varmekortet ovenfor markerer mørkere firkanter stærkere korrelationer. Fra matricen kan du se:

  • LSTAT
  • RM

Er stærkt korreleret med PRIS. En anden spændende egenskab er den stærke positive korrelation mellem NOX og INDUS, hvilket betyder, at disse to variabler bevæger sig i samme retning. Begge er også korreleret med PRIS. DIS er også stærkt korreleret med INDUS og NOX.

Du har et første hint om, at INDUS og NOX kan være gode kandidater til et interaktionsterm, og at DIS måske også er interessant at fokusere på.

Du kan gå en lille smule dybere ved at plotte et par-gitter. Det vil illustrere mere detaljeret det korrelationskort, du plottede før.

Pargitteret er sammensat som følger:

  • Overdel: Spredt plot med monteret linie
  • Diagonal: Kerneldensitetsplot
  • Nederste del: Multivariat kernedensitetsplot

Du fokuserer på fire uafhængige variabler. Valget svarer til de variabler med stærk korrelation med PRICE

  • INDUS
  • NOX
  • RM
  • LSTAT

desuden PRISEN.

Bemærk at standardfejlen tilføjes som standard til spredningsplottet.

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

Seaborn-pargitter af PRICE, INDUS, NOX, RM og LSTAT

Lad os begynde med den øverste del:

  • Prisen er negativt korreleret med INDUS, NOX og LSTAT; positivt korreleret med RM.
  • Der er en lille ikke-linearitet mellem LSTAT og PRICE
  • Der er ligesom en ret linje, når prisen er lig med 50. Fra beskrivelsen af ​​datasættet er PRICE blevet afkortet til værdien 50

Diagonal: NOX ser ud til at have to klynger, en omkring 0.5 og en omkring 0.85.

For at tjekke mere om det, kan du se på den nederste del. Den multivariate kerneltæthed er interessant på en måde, den farver, hvor de fleste af punkterne er. Forskellen med spredningsplottet tegner en sandsynlighedstæthed, selvom der ikke er noget punkt i datasættet for en given koordinat. Når farven er stærkere, indikerer det en høj koncentration af punkt omkring dette område.

Hvis du tjekker den multivariate tæthed for INDUS og NOX, kan du se den positive korrelation og de to klynger. Når industriens andel er over 18, er nitrogenoxidkoncentrationen over 0.6.

Du kan tænke på at tilføje en interaktion mellem INDUS og NOX i det lineære forhold.

Endelig kan du bruge det andet værktøj, der er skabt af Google, Dybdegående visning af facetter. Grænsefladen er opdelt i fire hovedsektioner. Det centrale område i midten er en zoombar visning af dataene. Øverst i panelet er der en rullemenu, hvor du kan ændre dataenes placering for at kontrollere facettering, placering og farve. Til højre er der en detaljeret visning af en bestemt datarække. Det betyder, at du kan klikke på en hvilken som helst dataprik i den midterste visualisering for at se detaljer om det pågældende datapunkt.

Under datavisualiseringstrinnet er du interesseret i at lede efter den parvise sammenhæng mellem den uafhængige variabel på husets pris. Det involverer dog mindst tre variabler, og 3D-plot er komplicerede at arbejde med.

En måde at løse dette problem på er at oprette en kategorisk variabel. Det vil sige, at vi kan oprette et 2D-plot og farvelægge prikkerne. Du kan opdele variablen PRICE i fire kategorier, hvor hver kategori er en kvartil (dvs. 0.25, 0.5, 0.75). Du kalder denne nye 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")

Punktdiagram af DIS mod INDUS farvet efter priskvartil

Brug af facetter dybdegående

For at åbne Deep Dive skal du transformere dataene til et json-format. Pandas har en metode til det: kald to_json på DataFrame.

Den første kodelinje angiver sprite-størrelsen i henhold til, hvor mange rækker datasættet indeholder.

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 nedenfor kommer fra Google GitHub. Når du har kørt koden, burde du kunne se dette:

Facetter Dybdegående facetteret scattervisning af Boston-datasættet

# 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 er interesseret i at se, om der er sammenhæng mellem branchesatsen, oxidkoncentrationen, afstanden til jobcenteret og husets pris.

Til det opdeler du først dataene efter brancheområde og farve med priskvartilen:

  • Vælg facettering X og vælg INDUS.
  • Vælg Display og vælg DIS. Det vil farve prikkerne med kvartilen af ​​boligprisen

Her betyder mørkere farver, at afstanden til det første jobcenter er større.

Indtil videre viser det igen, hvad du ved, lavere branchesats, højere pris. Nu kan du se opdelingen efter INDUX, efter NOX.

Vælg facettering Y og vælg NOX.

Nu kan man se huset langt fra det første jobcenter have den laveste brancheandel og dermed den laveste oxidkoncentration. Hvis du vælger at vise typen med Q_PRICE og zoome ned i nederste venstre hjørne, kan du se, hvilken type pris det er.

Du har endnu et hint om, at samspillet mellem IND, NOX og DIS kan være gode kandidater til at forbedre modellen.

Udforskningen har resulteret i to mulige interaktioner, så det næste skridt er at teste dem i en faktisk model.

Lineær regression med TensorFlow

I dette afsnit skal du estimere den lineære regressionsmodel med TensorFlow Estimator API. Du skal fortsætte som følger:

  • Forbered dataene
  • Estimer en benchmarkmodel: Ingen interaktion
  • Estimer en model med interaktion

Versionsnotat: og tf-estimator Pakken sendte sin endelige udgivelse med TensorFlow 2.15 og er fraværende fra TensorFlow 2.16 og fremefter, så tf.estimator.LinearRegressor kører kun på TensorFlow 1.x, medmindre du migrerer den til en Keras lineær model.

Husk, at målet med maskinlæring er at minimere fejlen. I dette tilfælde vinder modellen med den laveste gennemsnitlige kvadratiske fejl. TensorFlow-estimatoren beregner automatisk denne metrik.

Forberedelsesdata

I de fleste tilfælde er du nødt til at transformere dine data. Derfor er Facets Overview fascinerende. Ud fra den opsummerende statistik kan du se, at der er outliers. Disse værdier påvirker estimaterne, fordi de ikke ligner den population, du analyserer. Outliers skæver normalt resultaterne. For eksempel har en positiv outlier en tendens til at overvurdere koefficienten.

En god løsning til at løse dette problem er at standardisere variablen. Standardisering betyder en standardafvigelse på én og en gennemsnitsværdi på nul. Standardiseringsprocessen involverer to trin. Først og fremmest er det subtracts er middelværdien af ​​variablen. For det andet divideres den med standardafvigelsen, så fordelingen har en enhedsstandardafvigelse.

Biblioteket scikit-lære er nyttigt til at standardisere variabler. Du kan bruge modulets forbehandling med objektskalaen til dette formål.

Du kan bruge funktionen nedenfor til at skalere et datasæt. Bemærk, at du ikke skalerer etiketkolonnen og kategoriske 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 bruge funktionen til at konstruere det skalerede tog/testsæt.

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

Grundlæggende regression: Benchmark

Først og fremmest træner og tester du en model uden interaktion. Formålet er at se modellens præstationsmetrik.

Måden at træne modellen på er præcis som i vejledningen på API på højt niveau. Du skal bruge TensorFlow-estimatoren LinearRegressor.

Som en påmindelse skal du vælge:

  • funktionerne til at sætte i modellen
  • transformere funktionerne
  • konstruere den lineære regressor
  • konstruer input_fn-funktionen
  • træne modellen
  • test modellen

Du bruger alle variablerne i datasættet til at træne modellen. I alt er der tolv kontinuerlige variabler og én 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 konverterer funktionerne til en numerisk kolonne eller kategorisk kolonne

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 opretter modellen med linearRegressor. Du gemmer 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}

Hver kolonne i tog- eller testdataene konverteres til 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 estimerer modellen på togdataene.

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>

Til sidst estimerer du modellens ydeevne på testsættet

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}

Tabet af modellen er 1650.9785. Dette er den metrik, der skal slås i næste afsnit

Forbedre modellen: Interaktionsudtryk

I den første del af vejledningen så du en interessant sammenhæng mellem variablerne. De forskellige visualiseringsteknikker afslørede, at INDUS og NOX er forbundet og forstærker hinandens effekt på prisen. Ikke alene påvirker interaktionen mellem INDUS og NOX prisen, men denne effekt er også stærkere, når den interagerer med DIS.

Det er tid til at generalisere denne idé og se, om man kan forbedre modelforudsigelsen.

Du skal tilføje to nye kolonner til hvert datasæt: train og test. Til det formål opretter du én funktion til at beregne interaktionstermet og en anden til at beregne det tredobbelte interaktionsterm. Hver funktion producerer en enkelt kolonne. Når de nye variabler er oprettet, kan du sammenkæde dem med træningsdatasættet og testdatasættet.

Først og fremmest skal du oprette en ny variabel til interaktionen mellem INDUS og NOX.

Funktionen nedenfor returnerer to datarammer, train og test, med interaktionen mellem var_1 og var_2, i dit tilfælde INDUS og 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 gemmer de to nye kolonner

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

For det andet opretter du en anden funktion til at beregne det tredobbelte interaktionsled.

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 hvor du har alle nødvendige kolonner, kan du tilføje dem til at træne og teste datasæt. Du navngiver disse to nye dataramme:

  • 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

Træningsdataramme med kolonnerne INDUS_NOS og INDUS_NOS_DIS tilføjet

Det er det: du kan estimere den nye model med interaktionsleddene og se, hvordan præstationsmetrikken er.

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}

Det nye tab er 1515.9863. Bare ved at tilføje to nye variabler, var du i stand til at mindske tabet. Det betyder, at du kan lave en bedre forudsigelse end med benchmarkmodellen.

Model Funktionssæt Model bibliotek gennemsnitligt_tab off
benchmark 12 standardiserede kontinuerlige kolonner plus CHAS tog_Boston 86.89361 1650.9785
Med interaktion Benchmark plus INDUS_NOS og INDUS_NOS_DIS tog_Boston_1 79.78876 1515.9863

Begge tal stammer fra den samme testopdeling på 101 rækker, så faldet på cirka 8 procent i gennemsnitligt tab kan alene tilskrives de to interaktionskolonner.

Ofte Stillede Spørgsmål

Det blev udfaset i scikit-learn 1.0 og fjernet i 1.2. Datasættet indeholder en funktion, der er bygget på en antagelse om racemæssig selvadskillelse og huspriser, og den oprindelige undersøgelse validerede aldrig dens præmis om luftkvalitet. Boliger i Californien eller Ames er de sædvanlige erstatninger.

Et polynomielt led kvadrerer eller kuber en variabel for at bøje sin egen kurve. En interaktion multiplicerer to forskellige variable, så hældningen af ​​den ene afhænger af niveauet af den anden. Denne vejledning bygger den anden type, INDUS ganget med NOX.

Led efter par, der korrelerer med hinanden og med målet. Pearson-varmekortet og pargitteret gør dette visuelt; her klynger INDUS og NOX sig sammen, og begge track PRIS, som er det signal, der retfærdiggør at krydse dem.

Automatiserede feature-engineering-biblioteker genererer kandidattransformationer og krydsninger, scorer hver mod en holdout og beholder kun dem, der reducerer fejl. Det erstatter den manuelle heatmap-læsning, der er vist her, selvom et menneske stadig skal fornuftstjekke, hvad de genererede kolonner betyder.

Copilot håndterer gentagne plottninger i standardtekster godt — par gitre, maskerede varmekort, HTML-skabeloner til facetter. Tjek de argumenter, den foreslår, fordi seaborn omdøbte flere af dem, og Copilot blander gerne gamle og nuværende signaturer.

Nej. Tab skal sammenlignes på den samme hold-out-split, som det er tilfældet her. Et tab, der kun falder på træningsdata, signalerer overtilpasning, og tilføjelse af kolonner forbedrer næsten altid træningstilpasningen, uanset om de indeholder reel information eller ej.

Masken bruger np.bool, et alias der er udfaset i NumPy 1.20 og fjernet i 1.24. Nylige installationer giver AttributeError. Hvis man erstatter den indbyggede bool, forbliver opførslen identisk; np.bool_ fungerer også, hvis man har brug for NumPy-skalartypen.

CHAS er et kategorisk ja-eller-nej-flag, og PRICE er etiketten. Centrering og skalering af en dummy gør dens koefficient sværere at aflæse uden at ændre tilpasningen, og skalering af etiketten ville blot omskalere det rapporterede tab. Kun de tolv kontinuerlige prædiktorer er standardiserede.

Opsummer dette indlæg med: