TensorFlow lineaire regressie met facet- en interactieterm

⚡ Slimme samenvatting

Lineaire regressie op de woningmarktgegevens van Boston verbetert wanneer eerst de juiste interactietermen worden gevonden. Google Facetten maken die relaties visueel zichtbaar, en twee gekruiste kenmerken verlaagden het verlies in de TensorFlow-test van 1650 naar 1515.

  • 🔘 Eerst de data: Inzicht in verdelingen en uitschieters gaat vooraf aan elk model, omdat een model slechts een generalisatie is van een patroon dat je al hebt ontdekt.
  • ☑️ Facettenoverzicht: Statistieken per kenmerk tonen ontbrekende waarden, kolommen met veel nullen en de verschuiving in de trainings- versus testverdeling in één tabel.
  • ✅ Diepgaande analyse van de facetten: Door middel van facetten op basis van X en Y worden driewegrelaties omgezet in een leesbare 2D-grafiek, ingekleurd op basis van prijskwartiel.
  • 🧪 Correlatie-aflezing: De heatmap en het paarraster geven INDUS met NOX en DIS met beide aan als mogelijke interactiekandidaten.
  • ️ Standaardisatie: preprocessing.scale centreert de twaalf continue kolommen voordat de schatter ze te zien krijgt, waarbij CHAS en PRICE ongewijzigd blijven.
  • 📈 Gemeten winst: Door INDUS_NOS en INDUS_NOS_DIS toe te voegen, daalt het gemiddelde verlies op de testset van 86.89361 naar 79.78876.

TensorFlow lineaire regressie met facet- en interactieterm

TensorFlow lineaire regressie

In deze zelfstudie leert u hoe u de gegevens kunt controleren en voorbereiden om een ​​eenvoudige lineaire regressietaak te maken.

Deze zelfstudie is verdeeld in twee delen:

  • Zoek interactie
  • Test het model

In de vorige zelfstudie, je hebt de Boston-dataset gebruikt om de mediaanprijs van een huis te schatten. De Boston-dataset is klein, met slechts 506 observaties. Deze dataset wordt beschouwd als een benchmark om nieuwe lineaire regressiealgoritmen te proberen.

De dataset bestaat uit:

Veranderlijk Beschrijving
zn Het aandeel woongrond dat bestemd is voor kavels groter dan 25,000 vierkante meter.
onnodig Het aandeel hectaren niet-detailhandel per stad.
nox concentratie stikstofoxiden
rm gemiddeld aantal kamers per woning
leeftijd het aandeel koopwoningen gebouwd vóór 1940
dis gewogen afstanden tot vijf werkgelegenheidscentra in Boston
belasting onroerendgoedbelasting over de volledige waarde per dollar 10,000
ptratio de leerling-leraarratio per stad
met V De mediaanwaarde van koopwoningen in duizend dollar
crimineel criminaliteit per hoofd van de bevolking per stad
Chas Charles River dummy variabele (1 als grensrivier; 0 anders)
B het aandeel zwarten per stad

In deze tutorial schatten we de mediaanprijs met behulp van een lineaire regressor, maar de nadruk ligt op één specifiek proces van machine learning: "data voorbereiding."

Een model generaliseert het patroon in de gegevens. Om zo'n patroon vast te leggen, moet je het eerst vinden. Een goede gewoonte is om een ​​data-analyse uit te voeren voordat u een machine learning-algoritme uitvoert.

Het kiezen van de juiste kenmerken maakt het verschil in het succes van uw model. Stel je voor dat je probeert het loon van een volk te schatten. Als je het geslacht niet als covariaat meeneemt, krijg je een slechte schatting.

Een andere manier om het model te verbeteren is door te kijken naar de correlatie tussen de onafhankelijke variabele. Terug naar het voorbeeld: je kunt onderwijs zien als een uitstekende kandidaat om het loon maar ook het beroep te voorspellen. De eerlijkheid gebiedt te zeggen dat het beroep afhankelijk is van het opleidingsniveau, namelijk dat hoger onderwijs vaak leidt tot een beter beroep. Als we dit idee generaliseren, kunnen we zeggen dat de correlatie tussen de afhankelijke variabele en een verklarende variabele kan worden vergroot door nog een andere verklarende variabele.

Om het beperkte effect van opleiding op het beroep weer te geven, kunnen we een interactieterm gebruiken.

Interactieterm tussen opleiding en beroep weergegeven op een looncurve.

Als je naar de loonvergelijking kijkt, wordt het:

De loonvergelijking is uitgebreid met een interactieterm tussen opleiding en beroep.

If Het symbool voor de bètacoëfficiënt van de interactieterm. positief is, betekent dit dat een extra opleidingsniveau bij een hoge bezettingsgraad een hogere stijging van de mediaanwaarde van een woning oplevert. Er is met andere woorden sprake van een interactie-effect tussen opleiding en beroep.

Dezelfde schatterfamilie wordt ook gebruikt voor de lineaire classificator wanneer het label een klasse is in plaats van een prijs. In deze tutorial onderzoeken we welke variabelen goede kandidaten zijn voor interactietermen. We testen of het toevoegen van dit soort informatie leidt tot een betere prijsvoorspelling.

Samenvattende statistieken

Er zijn een paar stappen die je kunt volgen voordat je met het model aan de slag gaat. Zoals eerder vermeld, is het model een generalisatie van de data. De beste werkwijze is om eerst de data te begrijpen en daarna pas een voorspelling te doen. Als je je data niet kent, is de kans klein dat je je model kunt verbeteren.

Laad als eerste stap de gegevens als een Panda-dataframe en maak een trainingsset en testset.

Tips: Voor deze handleiding moet je matplotlib en seaborn geïnstalleerd hebben. PythonJe kunt een installatie uitvoeren. Python pakket meteen mee Jupyter. Je Zou niet doe dit

!conda install -- yes matplotlib

maar

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

Merk op dat deze stap niet nodig is als je matplotlib en seaborn geïnstalleerd hebt.

Matplotlib is de bibliotheek waarin u een grafiek kunt maken PythonSeaborn is een bibliotheek voor statistische visualisatie, gebouwd bovenop matplotlib. Het biedt onder andere de volgende mogelijkheden:traclevendige en prachtige percelen.

De onderstaande code importeert de benodigde bibliotheken.

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

De bibliotheek-sklearn bevat de Boston-dataset. U kunt de API aanroepen om de gegevens te importeren.

Versie-opmerking: load_boston werd afgekeurd in scikit-learn 1.0 en verwijderd in scikit-learn 1.2 omdat de dataset een raciaal geladen kenmerk bevat. Gebruik in een huidige installatie het volgende: fetch_california_housing Of laad het onbewerkte bestand zelf. De onderstaande workflow blijft ongewijzigd; alleen de loader verschilt.

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

De namen van de kenmerken worden als array opgeslagen in het object `feature_names`.

boston.feature_names

uitgang

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

U kunt de kolommen hernoemen.

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

De eerste twee rijen van de Boston DataFrame na het hernoemen van de kolommen.

Je converteert de variabele CHAS als een stringvariabele en labelt deze met ja als CHAS = 1 en nee als 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

Bij panda’s is het eenvoudig om de dataset te splitsen. Je verdeelt de dataset willekeurig met 80 procent trainingsset en 20 procent testset. Pandas Het beschikt over een ingebouwde samplingfunctie om een ​​dataframe te splitsen.

De eerste parameter frac is een waarde van 0 tot 1. U stelt deze in op 0.8 om willekeurig 80 procent van het dataframe te selecteren.

random_state corrigeert de shuffle, zodat dezelfde rijen voor iedereen worden geretourneerd.

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

U kunt de vorm van de gegevens achterhalen. Het zou moeten zijn:

  • Treinstel: 506*0.8 = 405
  • Testset: 506*0.2 = 101
print(df_train.shape, df_test.shape)

uitgang

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

uitgang

KRIMEN ZN INDUS CHAS NOX RM LEEFTIJD DIS RAD TAX PTRATIO B LSTAT PRIJS
0 0.00632 18.0 2.31 geen 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 geen 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 geen 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 geen 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 geen 0.524 6.172 96.1 5.9505 5.0 311.0 15.2 396.90 19.15 27.1

Gegevens zijn rommelig; het is vaak uit balans en bezaaid met uitschieters die de analyse en machine learning-training in de war brengen.

De eerste stap om de dataset op te schonen, is begrijpen waar deze moet worden opgeschoond. Het opschonen van een dataset kan lastig zijn, vooral op een generaliseerbare manier

De Google Het onderzoeksteam heeft hiervoor een tool ontwikkeld, genaamd facetten Dat helpt je de data te visualiseren en op allerlei manieren te analyseren. Dit is een goed uitgangspunt om te begrijpen hoe de dataset is opgebouwd.

Met Facets kunt u zien waar de gegevens er niet helemaal uitzien zoals u verwacht.

Met uitzondering van hun webapplicatie, Google maakt het eenvoudig om de toolkit in te sluiten in een Jupyter notebook.

Facetten bestaan ​​uit twee delen:

  • Overzicht facetten
  • Facetten diepe duik

Overzicht facetten

Facets Overview geeft een overzicht van de dataset. Facets Overview splitst de kolommen van de data in rijen met saillante informatie die laat zien

  1. het percentage ontbrekende observatie
  2. min- en max-waarden
  3. statistieken zoals het gemiddelde, de mediaan en de standaarddeviatie.
  4. Er wordt ook een kolom toegevoegd waarin het percentage waarden wordt weergegeven dat uit nullen bestaat, wat handig is als de meeste waarden uit nullen bestaan.
  5. Het is mogelijk om deze distributies te zien op de testdataset en de trainingsset voor elke feature. Dit betekent dat u dubbel kunt controleren of de test een vergelijkbare distributie heeft als de trainingsdata.

Dit is op zijn minst het minimum dat moet worden gedaan vóór elke machine learning-taak. Met deze tool mist u deze cruciale stap niet en worden enkele afwijkingen benadrukt.

Facetten diepe duik

Facets Deep Dive is een geweldige tool. Hiermee krijg je meer inzicht in je dataset en kun je inzoomen op individuele gegevens. Je kunt de data facetten op rij en kolom, gebaseerd op alle kenmerken van de dataset.

We zullen deze twee tools gebruiken met de Boston-dataset.

Note: U kunt Facets Overview en Facets Deep Dive niet tegelijkertijd gebruiken. U moet eerst het notitieboekje leegmaken om het gereedschap te kunnen wisselen.

Voordat een van beide tools gebruikt kan worden, moet Facets in de notebookomgeving geïnstalleerd zijn.

Facet installeren

Voor het grootste deel van de analyse kunt u de Facet-webapp gebruiken. In deze tutorial ziet u hoe u het kunt gebruiken binnen een Jupyter Notebook.

Allereerst moet u nbextensions installeren. Dat doet u met deze code. U kopieert en plakt de volgende code in de terminal van uw machine.

pip install jupyter_contrib_nbextensions

Direct daarna moet u de opslagplaatsen op uw computer klonen. Je hebt twee keuzes:

Optie 1) Kopieer en plak deze code in de terminal (Aanbevolen)

Als Git niet op uw computer is geïnstalleerd, ga dan naar deze pagina. URL Git voor Windows download pagina en volg de instructie. Als je klaar bent, kun je het git-commando in de terminal voor Mac-gebruikers of Anaconda-prompt gebruiken Windows gebruiker

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

Optie 2) Ga naar de PAIR-code/facets-repository en download de opslagplaatsen.

PAIR-code facets repositorypagina op GitHub

Op de bovenstaande pagina van de repository bevindt zich de downloadknop die bij optie 2 wordt gebruikt. Als u de eerste optie kiest, komt het bestand in uw downloadmap terecht. U kunt het bestand daar laten downloaden of naar een andere locatie slepen.

U kunt controleren waar Facets is opgeslagen met deze opdrachtregel:

echo `pwd`/`ls facets`

Nu u Facets hebt gevonden, moet u het installeren Jupyter Notitieboekje. U moet de werkmap instellen op het pad waar facetten zich bevinden.

Uw huidige werkmap en locatie van Facets-zip moeten hetzelfde zijn.

Terminal toont de map 'facets' in de huidige werkmap.

De bovenstaande uitvoer van de terminal bevestigt dat Facets zich in de huidige werkmap bevindt. Je moet de werkmap naar Facet laten verwijzen:

cd facets

Om Facetten in te installeren Jupyter, heb je twee opties. Als je hebt geïnstalleerd Jupyter met Conda voor alle gebruikers kopieert u deze code:

jupyter nbextension install facets-dist/

Gebruik anders:

jupyter nbextension install facets-dist/ --user

Oké, je bent er helemaal klaar voor. Laten we Facetoverzicht openen.

Voer het Facets-overzicht uit in Jupyter

Overzicht gebruikt a Python script om de statistieken te berekenen. U moet het script generic_feature_statistics_generator importeren naar Jupyter. Maak je geen zorgen; het script bevindt zich in de facettenbestanden.

Je moet het pad lokaliseren. Het is gemakkelijk te doen. Je opent facetten, opent het bestand facets_overview en vervolgens python. Kopieer het pad

Bestandspad van de python-map facets_overview

Ga daarna terug naar Jupyter, en schrijf de volgende code. Verander het pad '/Users/Thomas/facets/facets_overview/python' naar jouw pad.

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

U kunt het script importeren met de onderstaande code.

from generic_feature_statistics_generator import 
GenericFeatureStatisticsGenerator

In Windows wordt dezelfde code

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

from generic_feature_statistics_generator import GenericFeatureStatisticsGenerator

Om de featurestatistieken te berekenen, moet u de functie GenericFeatureStatistics gebruikenGenerator(), en u gebruikt het object ProtoFromDataFrames. U kunt het dataframe doorgeven aan een woordenboek. Als we bijvoorbeeld een samenvattende statistiek voor het treinstel willen maken, kunnen we de informatie in een woordenboek opslaan en deze gebruiken in het object `ProtoFromDataFrames“

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

Naam is de naam van de tabel die wordt weergegeven en u gebruikt de naam van de tabel waarvoor u de samenvatting wilt berekenen. In uw voorbeeld is de tabel met de gegevens 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")

Ten slotte kopieert en plakt u de onderstaande code. De code komt rechtstreeks van GitHub. Je zou dit moeten kunnen zien:

Overzichtstabel van facetten met samenvattende statistieken per kenmerk

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

Correlatiegrafiek en paarraster

Nadat je de gegevens en hun verdeling hebt gecontroleerd, kun je een correlatiematrix plotten. De correlatiematrix berekent de Pearson-coëfficiënt. Deze coëfficiënt ligt tussen -1 en 1, waarbij een positieve waarde een positieve correlatie aangeeft en een negatieve waarde een negatieve correlatie.

Je bent geïnteresseerd om te zien welke variabelen een goede kandidaat kunnen zijn voor interactietermen.

Versie-opmerking: het onderstaande masker roept np.bool, een alias die in NumPy 1.20 als verouderd werd beschouwd en verwijderd in NumPy 1.24In een recente versie van NumPy geeft dezelfde regel een foutmelding. AttributeError: module 'numpy' has no attribute 'bool'; de ingebouwde bool is de directe vervanging.

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

uitgang

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

Seaborn correlatie-heatmap van de Boston-variabelen

In de bovenstaande heatmap geven donkere vierkanten sterkere correlaties aan. Uit de matrix kunt u het volgende afleiden:

  • LSTAT
  • RM

Ze vertonen een sterke correlatie met de PRIJS. Een ander interessant kenmerk is de sterke positieve correlatie tussen NOX en INDUS, wat betekent dat deze twee variabelen in dezelfde richting bewegen. Beide zijn ook gecorreleerd met de PRIJS. DIS is eveneens sterk gecorreleerd met INDUS en NOX.

Je hebt een eerste aanwijzing dat INDUS en NOX goede kandidaten kunnen zijn voor een interactieterm en dat DIS wellicht ook interessant is om nader te onderzoeken.

Je kunt nog een beetje dieper gaan door een paarraster uit te zetten. Het zal de correlatiekaart die u eerder hebt uitgezet, gedetailleerder illustreren.

Het paarraster is als volgt samengesteld:

  • Bovenste deel: spreidingsdiagram met gepaste lijn
  • Diagonaal: plot van de kerneldichtheid
  • Onderste deel: plot van multivariate kerneldichtheid

Je concentreert je op vier onafhankelijke variabelen. De keuze komt overeen met de variabelen die een sterke correlatie hebben met de PRIJS.

  • INDUS
  • NOX
  • RM
  • LSTAT

bovendien de PRIJS.

Note dat de standaardfout standaard wordt toegevoegd aan het spreidingsdiagram.

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)

uitgang

Seaborn-raster met paren van PRIJS, INDUS, NOX, RM en LSTAT

Laten we beginnen met het bovenste gedeelte:

  • Prijs is negatief gecorreleerd met INDUS, NOX en LSTAT; positief gecorreleerd met RM.
  • Er is een lichte niet-lineariteit tussen LSTAT en PRICE.
  • Er is een soort rechte lijn wanneer de prijs gelijk is aan 50. Uit de beschrijving van de dataset blijkt dat PRICE is afgekapt op de waarde 50

Diagonaal: NOX lijkt twee clusters te hebben, één rond de 0.5 en één rond de 0.85.

Om er meer over te weten te komen, kunt u naar het onderste gedeelte kijken. De Multivariate Kernel Density is interessant in zekere zin, het kleurt waar de meeste punten zijn. Het verschil met de scatterplot tekent een waarschijnlijkheidsdichtheid, ook al is er geen punt in de dataset voor een gegeven coördinaat. Wanneer de kleur sterker is, geeft dit een hoge concentratie van punten rond dit gebied aan.

Als u de multivariate dichtheid voor INDUS en NOX controleert, ziet u de positieve correlatie en de twee clusters. Wanneer het aandeel van de industrie boven de 18 ligt, ligt de stikstofoxideconcentratie boven de 0.6.

Je kunt nadenken over het toevoegen van een interactie tussen INDUS en NOX in de lineaire relatie.

Tot slot kunt u de tweede tool gebruiken die is gemaakt door GoogleFacets Deep Dive. De interface is verdeeld in vier hoofdsecties. Het centrale gedeelte toont een inzoombaar overzicht van de gegevens. Bovenaan het paneel bevindt zich een uitklapmenu waarmee u de weergave van de gegevens kunt aanpassen, zoals facetten, positionering en kleur. Aan de rechterkant ziet u een gedetailleerde weergave van een specifieke rij gegevens. U kunt dus op een willekeurig gegevenspunt in de centrale visualisatie klikken om de details van dat specifieke gegevenspunt te bekijken.

Tijdens de stap van datavisualisatie bent u geïnteresseerd in het zoeken naar de paargewijze correlatie tussen de onafhankelijke variabele op de prijs van het huis. Het omvat echter ten minste drie variabelen en 3D-plots zijn ingewikkeld om mee te werken.

Een manier om dit probleem aan te pakken is door een categorische variabele te creëren. Dat wil zeggen, we kunnen een 2D-grafiek maken en de punten kleuren. Je kunt de variabele PRIJS opsplitsen in vier categorieën, waarbij elke categorie een kwartiel is (bijvoorbeeld 0.25, 0.5, 0.75). Je noemt deze nieuwe variabele 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")

Spreidingsdiagram van DIS ten opzichte van INDUS, gekleurd per prijskwartiel.

Diepgaande analyse met behulp van Facets

Om Deep Dive te openen, moet je de gegevens omzetten naar een JSON-formaat. Pandas heeft daarvoor een methode: roep de `to_json`-methode aan op de `DataFrame`.

De eerste regel code stelt de spritegrootte in op basis van het aantal rijen in de 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')

De onderstaande code is afkomstig van Google GitHub. Nadat je de code hebt uitgevoerd, zou je dit moeten zien:

Facets Deep Dive: een gefacetteerde scatter-weergave van de Boston-dataset.

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

U bent geïnteresseerd om te zien of er een verband bestaat tussen het sectortarief, de oxideconcentratie, de afstand tot het arbeidsbureau en de prijs van het huis.

Daarvoor splitst u de gegevens eerst op per branche en kleur met het prijskwartiel:

  • Selecteer facettering X en kies INDUS.
  • Selecteer Weergave en kies DIS. Het kleurt de stippen met het kwartiel van de huizenprijs

Hier betekenen donkere kleuren dat de afstand tot het eerste arbeidsbureau groter is.

Tot nu toe laat het opnieuw zien wat je weet: een lager industrietarief, een hogere prijs. Nu kunt u de uitsplitsing bekijken per INDUX, per NOX.

Selecteer facet Y en kies NOX.

Nu kunt u zien dat het huis ver van het eerste jobcentrum het laagste aandeel in de industrie heeft en daarom de laagste oxideconcentratie. Als u ervoor kiest om het type weer te geven met Q_PRICE en de linkerbenedenhoek inzoomt, kunt u zien wat voor soort prijs het is.

U heeft nog een aanwijzing dat de interactie tussen IND, NOX en DIS goede kandidaten kan zijn om het model te verbeteren.

Het onderzoek heeft twee mogelijke interacties opgeleverd, dus de volgende stap is om deze in een daadwerkelijk model te testen.

Lineaire regressie met TensorFlow

In dit gedeelte schat u het lineaire regressiemodel met behulp van de TensorFlow Estimator API. U gaat als volgt te werk:

  • Bereid de gegevens voor
  • Schat een benchmarkmodel: geen interactie
  • Schat een model met interactie

Versie-opmerking: the tf-estimator Het pakket werd voor het laatst uitgebracht met TensorFlow 2.15 en is niet meer beschikbaar vanaf TensorFlow 2.16. tf.estimator.LinearRegressor Werkt alleen met TensorFlow 1.x, tenzij je het migreert naar een lineair Keras-model.

Onthoud dat het doel van machine learning is om de fout te minimaliseren. In dit geval wint het model met de laagste gemiddelde kwadratische fout. De TensorFlow-estimator berekent deze waarde automatisch.

Voorbereidingsgegevens

In de meeste gevallen moet je je data transformeren. Daarom is Facets Overview zo fascinerend. Uit de samenvattende statistieken zie je dat er uitschieters zijn. Deze waarden beïnvloeden de schattingen omdat ze niet overeenkomen met de populatie die je analyseert. Uitschieters vertekenen de resultaten meestal. Een positieve uitschieter heeft bijvoorbeeld de neiging om de coëfficiënt te overschatten.

Een goede oplossing voor dit probleem is het standaardiseren van de variabele. Standaardisatie betekent een standaarddeviatie van één en een gemiddelde van nul. Het standaardisatieproces bestaat uit twee stappen. Allereerst wordt de variabele gestandaardiseerd.tracts is de gemiddelde waarde van de variabele. Ten tweede wordt deze gedeeld door de standaarddeviatie, zodat de verdeling een standaarddeviatie van 1 heeft.

De bibliotheek scikit-leren Het is handig om variabelen te standaardiseren. Je kunt hiervoor de module 'preprocessing' gebruiken met het object 'scale'.

U kunt de onderstaande functie gebruiken om een ​​gegevensset te schalen. Houd er rekening mee dat u de labelkolom en categorische variabelen niet schaalt.

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

U kunt de functie gebruiken om de trein/testset op schaal te construeren.

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

Basisregressie: benchmark

Allereerst train en test je een model zonder interactie. Het doel is om de prestatiemetriek van het model te zien.

De manier om het model te trainen is precies zoals beschreven in de handleiding op de website. API op hoog niveau. Je maakt gebruik van de TensorFlow schatter LinearRegressor.

Ter herinnering: u moet kiezen:

  • de kenmerken die in het model moeten worden geplaatst
  • transformeer de kenmerken
  • construeer de lineaire regressor
  • construeer de input_fn-functie
  • train het model
  • test het model

Je gebruikt alle variabelen in de dataset om het model te trainen. In totaal zijn er twaalf continue variabelen en één categorische variabele.

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

U converteert de features naar een numerieke kolom of categorische kolom

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'])]

U maakt het model met de linearRegressor. Je bewaart het model in de map train_Boston

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

uitgang

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}

Elke kolom in de trainings- of testgegevens wordt met de functie get_input_fn omgezet in een Tensor.

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)

Je schat het model op basis van de treingegevens.

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

uitgang

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>

Tenslotte schat je de prestaties van het model op de testset in

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

uitgang

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}

Het verlies van het model is 1650.9785. Dit is de maatstaf die in de volgende sectie moet worden overtroffen

Verbeter het model: Interactieterm

Tijdens het eerste deel van de tutorial zag u een interessante relatie tussen de variabelen. De verschillende visualisatietechnieken lieten zien dat INDUS en NOX met elkaar verbonden zijn en elkaars effect op de prijs versterken. Niet alleen de interactie tussen INDUS en NOX beïnvloedt de prijs, maar dit effect is ook sterker wanneer er een interactie plaatsvindt met DIS.

Het is tijd om dit idee te generaliseren en te kijken of je de voorspellingskracht van het model kunt verbeteren.

Je moet twee nieuwe kolommen aan elke dataset toevoegen: trainings- en testdataset. Daarvoor maak je een functie om de interactieterm te berekenen en een andere om de drievoudige interactieterm te berekenen. Elke functie produceert één kolom. Nadat de nieuwe variabelen zijn aangemaakt, kun je ze samenvoegen met de trainingsdataset en de testdataset.

Allereerst moet u een nieuwe variabele aanmaken voor de interactie tussen INDUS en NOX.

De onderstaande functie retourneert twee dataframes, train en test, met de interactie tussen var_1 en var_2, in jouw geval INDUS en 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

U slaat de twee nieuwe kolommen op

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

Ten tweede maak je een tweede functie om de drievoudige interactieterm te berekenen.

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 u over alle benodigde kolommen beschikt, kunt u deze toevoegen aan het trainen en testen van de gegevensset. U noemt deze twee nieuwe dataframes:

  • df_train_nieuw
  • df_test_nieuw
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)

uitgang

Trainingsdataframe waaraan de kolommen INDUS_NOS en INDUS_NOS_DIS zijn toegevoegd.

Dat is alles: je kunt het nieuwe model schatten met de interactietermen en zien hoe de prestatiemaatstaf presteert.

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)

uitgang

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)

uitgang

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)

uitgang

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}

Het nieuwe verlies is 1515.9863. Door slechts twee nieuwe variabelen toe te voegen, kon je het verlies verkleinen. Hierdoor kunt u een betere voorspelling doen dan met het benchmarkmodel.

Model Functieset Modellijst gemiddeld verlies uit
criterium 12 gestandaardiseerde continue kolommen plus CHAS trein_Boston 86.89361 1650.9785
Met interactie Benchmark plus INDUS_NOS en INDUS_NOS_DIS trein_Boston_1 79.78876 1515.9863

Beide cijfers zijn afkomstig van dezelfde test met 101 rijen, dus de daling van ongeveer 8 procent in het gemiddelde verlies is uitsluitend toe te schrijven aan de twee interactiekolommen.

Veelgestelde vragen

Het werd afgekeurd in scikit-learn 1.0 en verwijderd in 1.2. De dataset bevat een kenmerk dat gebaseerd is op een aanname over raciale zelfsegregatie en huizenprijzen, en de oorspronkelijke studie heeft de aanname over luchtkwaliteit nooit gevalideerd. Woningen in Californië of Ames worden vaak als alternatief gebruikt.

Een polynoomterm kwadrateert of kubiseert één variabele om zijn eigen curve te buigen. Een interactie vermenigvuldigt twee verschillende variabelen, waardoor de helling van de ene afhangt van de waarde van de andere. Deze tutorial bouwt het tweede type, INDUS maal NOX.

Zoek naar paren die met elkaar en met het doel correleren. De Pearson-heatmap en het paarraster doen dit visueel; hier clusteren INDUS en NOX samen en beide track PRIJS, dat is het signaal dat de kruising rechtvaardigt.

Geautomatiseerde feature-engineeringbibliotheken genereren kandidaat-transformaties en kruisingen, beoordelen elk ervan ten opzichte van een testset en behouden alleen de transformaties die de foutmarge verkleinen. Dit vervangt het handmatig lezen van de heatmap zoals hier getoond, hoewel een mens nog steeds moet controleren wat de gegenereerde kolommen betekenen.

Copilot kan goed overweg met repetitieve, standaard plotfuncties, zoals paarroosters, gemaskeerde heatmaps en HTML-sjablonen voor facetten. Controleer de voorgestelde argumenten, want seaborn heeft er een aantal hernoemd en Copilot kan zonder problemen oude en huidige signatures combineren.

Nee. Het verlies moet worden vergeleken op dezelfde aparte dataset, zoals hier het geval is. Een verlies dat alleen op de trainingsdata daalt, duidt op overfitting, en het toevoegen van kolommen verbetert de trainingsfit bijna altijd, ongeacht of ze daadwerkelijke informatie bevatten.

Het masker gebruikt np.bool, een alias die in NumPy 1.20 als verouderd werd beschouwd en in 1.24 is verwijderd. Recente installaties geven een AttributeError. Het vervangen van np.bool door de ingebouwde bool levert hetzelfde gedrag op; np.bool_ werkt ook als je het scalaire NumPy-type nodig hebt.

CHAS is een categorische ja-of-nee-vlag en PRICE is het label. Het centreren en schalen van een dummyvariabele maakt de coëfficiënt ervan moeilijker leesbaar zonder de fit te veranderen, en het schalen van het label zou simpelweg het gerapporteerde verlies herschalen. Alleen de twaalf continue voorspellers zijn gestandaardiseerd.

Vat dit bericht samen met: