Regresja liniowa TensorFlow z aspektem i terminem interakcji

W tym samouczku dowiesz się, jak sprawdzić dane i przygotować je do utworzenia prostego zadania regresji liniowej.

Ten samouczek jest podzielony na dwie części:

  • Szukaj interakcji
  • Przetestuj model

W poprzedni samouczek, użyłeś zestawu danych Boston, aby oszacować medianę ceny domu. Zestaw danych Boston ma niewielki rozmiar, zawiera tylko 506 obserwacji. Ten zestaw danych jest uważany za punkt odniesienia do wypróbowania nowych algorytmów regresji liniowej.

Zbiór danych składa się z:

Zmienna Opisy Konstrukcyjne
zn Udział gruntów mieszkalnych przeznaczonych na działki o powierzchni powyżej 25,000 XNUMX stóp kwadratowych.
indus Udział powierzchni użytków niehandlowych w przeliczeniu na miasto.
nox stężenie tlenków azotu
rm średnia liczba pokoi w mieszkaniu
wiek odsetek mieszkań własnościowych wybudowanych przed 1940 rokiem
dis odległości ważone do pięciu bostońskich centrów zatrudnienia
podatek pełnowartościowa stawka podatku od nieruchomości na 10,000 XNUMX dolarów
ptratio stosunek liczby uczniów do nauczycieli według miasta
med Średnia wartość domów zamieszkałych przez właścicieli w tysiącach dolarów
kryminalny wskaźnik przestępczości na mieszkańca według miasta
chas Zmienna fikcyjna rzeki Charles (1, jeśli ogranicza rzekę; 0 w przeciwnym wypadku)
B odsetek czarnych w mieście

W tym samouczku oszacujemy średnią cenę za pomocą regresora liniowego, ale skupimy się na jednym konkretnym procesie uczenie maszynowe: "przygotowywanie danych."

Model uogólnia wzór w danych. Aby uchwycić taki wzór, musisz go najpierw znaleźć. Dobrą praktyką jest przeprowadzenie analizy danych przed uruchomieniem dowolnego algorytmu uczenia maszynowego.

Wybór odpowiednich funkcji ma decydujący wpływ na sukces Twojego modelu. Wyobraź sobie, że próbujesz oszacować płacę danej osoby. Jeśli nie uwzględnisz płci jako współzmiennej, otrzymasz kiepski szacunek.

Innym sposobem ulepszenia modelu jest przyjrzenie się korelacji między zmienną niezależną. Wracając do przykładu, możesz pomyśleć o edukacji jako o doskonałym czynniku pozwalającym przewidzieć płacę, ale także zawód. Można powiedzieć, że zawód zależy od poziomu wykształcenia, a mianowicie wyższe wykształcenie często prowadzi do lepszego zawodu. Jeśli uogólnimy tę koncepcję, możemy powiedzieć, że korelację między zmienną zależną a zmienną objaśniającą można wzmocnić w przypadku jeszcze jednej zmiennej objaśniającej.

Aby uchwycić ograniczony wpływ wykształcenia na zawód, możemy użyć terminu interakcji.

Okres interakcji

Jeśli spojrzeć na równanie płac, wygląda to następująco:

Okres interakcji

If Okres interakcji jest dodatnia, to oznacza, że ​​dodatkowy poziom wykształcenia powoduje większy wzrost mediany wartości domu dla wysokiego poziomu zatrudnienia. Innymi słowy, istnieje efekt interakcji pomiędzy edukacją a zawodem.

W tym samouczku spróbujemy sprawdzić, które zmienne mogą być dobrymi kandydatami na terminy interakcji. Przetestujemy, czy dodanie tego rodzaju informacji prowadzi do lepszego przewidywania cen.

Statystyki podsumowujące

Zanim przejdziesz do modelu, możesz wykonać kilka kroków. Jak wspomniano wcześniej, model jest uogólnieniem danych. Najlepszą praktyką dopasowania jest zrozumienie danych i dokonanie prognozy. Jeśli nie znasz swoich danych, masz niewielkie szanse na ulepszenie swojego modelu.

W pierwszym kroku załaduj dane jako ramkę danych Pandy i utwórz zbiór treningowy i testowy.

Wskazówki: Aby skorzystać z tego samouczka, musisz mieć zainstalowane programy Matplotlit i Seaborn Python. Możesz zainstalować Python pakiet w locie z Jupyter. Ty Nie powinieneś Zrób to

!conda install -- yes matplotlib

ale

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

Zauważ, że ten krok nie jest konieczny, jeśli masz zainstalowane matplotlib i seaborn.

Matplotlib to biblioteka, w której można tworzyć wykresy Python. Seaborn to biblioteka wizualizacji statystycznej zbudowana na bazie matplotlib. Oferuje atrakcyjne i piękne działki.

Poniższy kod importuje niezbędne biblioteki.

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

Biblioteka sklearn zawiera zbiór danych Boston. Możesz wywołać jego API, aby zaimportować dane.

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

Nazwy funkcji są przechowywane w obiekcie feature_names w tablicy.

boston.feature_names

Wydajność

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

Możesz zmienić nazwy kolumn.

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

Regresja liniowa z aspektem i terminem interakcji

Konwertujesz zmienną CHAS na zmienną łańcuchową i oznaczysz ją tak, jeśli CHAS = 1 i nie, jeśli 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

W przypadku pand podział zbioru danych jest prosty. Losowo dzielisz zbiór danych na 80% zestawu treningowego i 20% zestawu testowego. Pandy mają wbudowaną funkcję kosztu umożliwiającą podzielenie próbki ramki danych.

Pierwszy parametr frac ma wartość od 0 do 1. Ustawiasz go na 0.8, aby losowo wybrać 80 procent ramki danych.

Random_state pozwala na zwrócenie tej samej ramki danych dla wszystkich.

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

Możesz uzyskać kształt danych. Powinno być:

  • Zestaw pociągowy: 506*0.8 = 405
  • Zbiór testowy: 506*0.2 = 101
print(df_train.shape, df_test.shape)

Wydajność

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

Wydajność

KRYM ZN INDUS CHAS NOX RM WIEK DIS RAD PODATEK PTRACJA B LSTAT CENA
0 0.00632 18.0 2.31 Nie 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 Nie 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 Nie 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 Nie 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 Nie 0.524 6.172 96.1 5.9505 5.0 311.0 15.2 396.90 19.15 27.1

Dane są nieuporządkowane; często jest źle zbilansowany i posypany wartościami odstającymi, które zakłócają analizę i szkolenie w zakresie uczenia maszynowego.

Pierwszym krokiem do oczyszczenia zbioru danych jest zrozumienie, gdzie wymaga on oczyszczenia. Oczyszczenie zbioru danych może być trudne, szczególnie w przypadku, gdy można go uogólnić

Zespół badawczy Google opracował narzędzie do tego zadania o nazwie Fasety które pomagają wizualizować dane i dzielić je na różne sposoby. Jest to dobry punkt wyjścia do zrozumienia sposobu ułożenia zbioru danych.

Aspekty pozwalają znaleźć miejsca, w których dane nie wyglądają tak, jak myślisz.

Z wyjątkiem aplikacji internetowej Google ułatwia osadzanie zestawu narzędzi w pliku Jupyter notatnik.

Fasety składają się z dwóch części:

  • Przegląd aspektów
  • Głębokie nurkowanie w aspektach

Przegląd aspektów

Przegląd Facets daje przegląd zestawu danych. Przegląd Facets dzieli kolumny danych na wiersze zawierające istotne informacje, pokazując

  1. procent brakujących obserwacji
  2. wartości minimalne i maksymalne
  3. statystyki, takie jak średnia, mediana i odchylenie standardowe.
  4. Dodaje również kolumnę pokazującą procent wartości będących zerami, co jest przydatne, gdy większość wartości to zera.
  5. Można zobaczyć te rozkłady na zestawie danych testowych, jak również na zestawie treningowym dla każdej funkcji. Oznacza to, że można dwukrotnie sprawdzić, czy test ma podobny rozkład do danych treningowych.

Jest to przynajmniej minimum, które należy wykonać przed jakimkolwiek zadaniem uczenia maszynowego. Dzięki temu narzędziu nie przegapisz tego kluczowego kroku i uwypuklisz pewne nieprawidłowości.

Głębokie nurkowanie w aspektach

Facets Deep Dive to fajne narzędzie. Pozwala uzyskać pewną przejrzystość w zestawie danych i maksymalnie powiększyć, aby zobaczyć pojedynczy fragment danych. Oznacza to, że możesz podzielić dane na fasety według wiersza i kolumny w obrębie dowolnych cech zestawu danych.

Będziemy używać tych dwóch narzędzi w przypadku zbioru danych Boston.

Note: Nie można jednocześnie używać funkcji Przegląd aspektów i Głębokie nurkowanie. Aby zmienić narzędzie, musisz najpierw wyczyścić notatnik.

Zainstaluj Faceta

Do większości analiz można używać aplikacji internetowej Facet. W tym samouczku zobaczysz, jak go używać w pliku Jupyter Notatnik.

Przede wszystkim musisz zainstalować nbextensions. Robisz to za pomocą tego kodu. Kopiujesz i wklejasz następujący kod w terminalu swojego komputera.

pip install jupyter_contrib_nbextensions

Zaraz po tym musisz sklonować repozytoria na swoim komputerze. Masz dwie możliwości:

Opcja 1) Skopiuj i wklej ten kod w terminalu (Zalecana)

Jeśli nie masz zainstalowanego Gita na swoim komputerze, przejdź pod ten adres URL https://git-scm.com/download/win i postępuj zgodnie z instrukcją. Gdy już skończysz, możesz użyć polecenia git w terminalu dla użytkownika Mac lub Monituj o Anacondę Windows użytkownik

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

Opcja 2) Iść do https://github.com/PAIR-code/facets i pobierz repozytoria.

Zainstaluj Faceta

Jeśli wybierzesz pierwszą opcję, plik trafi do pliku do pobrania. Możesz pozwolić na pobranie pliku lub przeciągnąć go na inną ścieżkę.

Możesz sprawdzić, gdzie przechowywane są aspekty, za pomocą tego wiersza poleceń:

echo `pwd`/`ls facets`

Teraz, gdy już zlokalizowałeś Facets, musisz go zainstalować Jupyter Zeszyt. Musisz ustawić katalog roboczy na ścieżkę, w której znajdują się aspekty.

Twój obecny katalog roboczy i lokalizacja zip Facets powinny być takie same.

Zainstaluj Faceta

Musisz wskazać katalog roboczy na Facet:

cd facets

Aby zainstalować Facets w Jupyter, masz dwie możliwości. Jeśli zainstalowałeś Jupyter z Condą dla wszystkich użytkowników, skopiuj ten kod:

można użyć jupyter nbextension install facets-dist/

jupyter nbextension install facets-dist/

W przeciwnym wypadku użyj:

jupyter nbextension install facets-dist/ --user

W porządku, wszystko gotowe. Otwórzmy Przegląd aspektów.

O platformie

Przegląd wykorzystuje a Python skrypt do obliczania statystyk. Musisz zaimportować skrypt o nazwie generic_feature_statistics_generator do Jupyter. Nie martw się; skrypt znajduje się w plikach aspektów.

Musisz zlokalizować jego ścieżkę. Można to łatwo zrobić. Otwierasz aspekty, otwierasz plik facets_overview, a następnie python. Skopiuj ścieżkę

Przegląd aspektu

Następnie wróć do Jupyteri napisz następujący kod. Zmień ścieżkę '/Users/Thomas/facets/facets_overview/python' na swoją ścieżkę.

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

Możesz zaimportować skrypt za pomocą poniższego kodu.

from generic_feature_statistics_generator import 
GenericFeatureStatisticsGenerator

W systemie Windows ten sam kod staje się

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

from generic_feature_statistics_generator import GenericFeatureStatisticsGenerator

Aby obliczyć statystyki cech, należy skorzystać z funkcji GenericFeatureStatisticsGenerator() i używasz obiektu ProtoFromDataFrames. Możesz przekazać ramkę danych do słownika. Na przykład, jeśli chcemy utworzyć statystykę podsumowującą dla składu, możemy zapisać tę informację w słowniku i użyć jej w obiekcie „ProtoFromDataFrames”

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

Nazwa to nazwa wyświetlanej tabeli. Używasz nazwy tabeli, dla której chcesz obliczyć podsumowanie. W Twoim przykładzie tabela zawierająca dane to 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")

Na koniec wystarczy skopiować i wkleić poniższy kod. Kod pochodzi bezpośrednio z GitHuba. Powinieneś być w stanie to zobaczyć:

Przegląd aspektu

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

HTML_TEMPLATE = """<link rel="import" href="/pl/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))

Wykres

Po sprawdzeniu danych i ich rozkładu można wykreślić macierz korelacji. Macierz korelacji oblicza współczynnik Pearsona. Współczynnik ten jest powiązany pomiędzy -1 i 1, przy czym wartość dodatnia wskazuje na dodatnią korelację, a wartość ujemna na ujemną korelację.

Chcesz zobaczyć, które zmienne mogą być dobrymi kandydatami na warunki interakcji.

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

Wydajność

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

png

Wykres aspektowy

Z matrixa możesz zobaczyć:

  • LSTAT
  • RM

Są silnie skorelowane z PRICE. Inną ekscytującą cechą jest silna dodatnia korelacja między NOX i INDUS, co oznacza, że ​​te dwie zmienne poruszają się w tym samym kierunku. Poza tym są również skorelowane z PRICE. DIS jest również silnie skorelowany z IND i NOX.

Masz pierwszą wskazówkę, że IND i NOX mogą być dobrymi kandydatami na termin przechwytujący, a DIS również może być interesujący, na którym warto się skupić.

Możesz zejść nieco głębiej, rysując siatkę par. Zilustruje to bardziej szczegółowo mapę korelacji, którą narysowałeś wcześniej.

Siatkę par składamy w następujący sposób:

  • Górna część: Wykres punktowy z dopasowaną linią
  • Przekątna: Wykres gęstości jądra
  • Dolna część: Wielowymiarowy wykres gęstości jądra

Wybierasz skupienie się na czterech zmiennych niezależnych. Wybór odpowiada zmiennym o silnej korelacji z PRICE

  • INDUS
  • NOX
  • RM
  • LSTAT

ponadto CENA.

Note że błąd standardowy jest domyślnie dodawany do wykresu punktowego.

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)

Wydajność

Wykres aspektowy

Zacznijmy od górnej części:

  • Cena jest ujemnie skorelowana z INDUS, NOX i LSTAT; dodatnio skorelowane z RM.
  • W przypadku LSTAT i PRICE występuje niewielka nieliniowość
  • Jest jak linia prosta, gdy cena jest równa 50. Z opisu zbioru PRICE została obcięta do wartości 50

Przekątna

  • Wydaje się, że NOX tworzy dwa skupiska: jedno wokół 0.5 i jedno wokół 0.85.

Aby dowiedzieć się więcej, możesz spojrzeć na dolną część. Multivariate Kernel Density jest interesujący w tym sensie, że koloruje miejsca, w których znajduje się większość punktów. Różnica z wykresem punktowym rysuje gęstość prawdopodobieństwa, nawet jeśli w zestawie danych nie ma żadnego punktu dla danej współrzędnej. Gdy kolor jest mocniejszy, wskazuje to na wysokie skupienie punktów wokół tego obszaru.

Jeśli sprawdzisz gęstość wielowymiarową dla INDUS i NOX, zobaczysz dodatnią korelację i dwa klastry. Gdy udział branży przekracza 18, stężenie tlenków azotu przekracza 0.6.

Można pomyśleć o dodaniu interakcji pomiędzy INDUS i NOX w zależności liniowej.

Na koniec możesz użyć drugiego narzędzia stworzonego przez Google, Facets Deep Dive. Interfejs jest podzielony na cztery główne sekcje. Centralny obszar w środku to powiększalny wyświetlacz danych. Na górze panelu znajduje się menu rozwijane, w którym możesz zmienić układ danych, aby kontrolować faceting, pozycjonowanie i kolor. Po prawej stronie znajduje się szczegółowy widok określonego wiersza danych. Oznacza to, że możesz kliknąć dowolny punkt danych w środkowej wizualizacji, aby zobaczyć szczegóły dotyczące tego konkretnego punktu danych.

Podczas etapu wizualizacji danych interesuje Cię poszukiwanie korelacji parami między zmienną niezależną a ceną domu. Jednak obejmuje to co najmniej trzy zmienne, a wykresy 3D są skomplikowane w obsłudze.

Jednym ze sposobów rozwiązania tego problemu jest utworzenie zmiennej kategorycznej. Oznacza to, że możemy stworzyć wykres 2D pokolorując kropkę. Możesz podzielić zmienną PRICE na cztery kategorie, przy czym każda kategoria jest kwartylem (tj. 0.25, 0.5, 0.75). Nazywasz tę nową zmienną 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")

Wykres aspektowy

Głębokie nurkowanie w aspektach

Aby otworzyć Deep Dive, musisz przekształcić dane w format json. Pandy jako obiekt do tego. Możesz użyć to_json po zestawie danych Pandas.

Pierwsza linia kodu obsługuje rozmiar zestawu danych.

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

Poniższy kod pochodzi z Google GitHub. Po uruchomieniu kodu powinieneś zobaczyć to:

Głębokie nurkowanie w aspektach

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

# Create Facets template  
HTML_TEMPLATE = """<link rel="import" href="/pl/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))

Interesuje Cię, czy istnieje związek pomiędzy stawką w branży, stężeniem tlenków, odległością od urzędu pracy i ceną domu.

W tym celu najpierw dzielisz dane według zakresu branży i koloru z kwartylem ceny:

  • Wybierz fasetowanie X i wybierz INDUS.
  • Wybierz Wyświetlacz i wybierz DIS. Pokoloruje kropki kwartylem ceny domu

tutaj ciemniejsze kolory oznaczają, że do pierwszego urzędu pracy jest daleko.

Jak dotąd pokazuje ponownie to, co wiesz, niższą stawkę branżową, wyższą cenę. Teraz możesz spojrzeć na podział według INDUX i NOX.

  • Wybierz fasetowanie Y i wybierz NOX.

Teraz możesz zobaczyć, że dom oddalony od pierwszego centrum pracy ma najniższy udział w przemyśle, a zatem najniższe stężenie tlenku. Jeśli wybierzesz wyświetlanie typu z Q_PRICE i powiększysz lewy dolny róg, możesz zobaczyć, jaki to typ ceny.

Masz kolejną wskazówkę, że interakcja między IND, NOX i DIS może być dobrym kandydatem do ulepszenia modelu.

TensorFlow

W tej sekcji oszacujesz klasyfikator liniowy za pomocą API estymatorów TensorFlow. Będziesz postępować w następujący sposób:

  • Przygotuj dane
  • Oszacuj model porównawczy: Brak interakcji
  • Oszacuj model z interakcją

Pamiętaj, że celem uczenia maszynowego jest minimalizacja błędu. W tym przypadku zwycięży model z najmniejszym błędem średniokwadratowym. Estymator TensorFlow automatycznie oblicza tę metrykę.

Dane przygotowania

W większości przypadków musisz przekształcić swoje dane. Dlatego właśnie Przegląd aspektów jest fascynujący. Ze statystyk podsumowujących wynika, że ​​istnieją wartości odstające. Wartości te wpływają na szacunki, ponieważ nie przypominają analizowanej populacji. Wartości odstające zwykle zaburzały wyniki. Na przykład dodatnia wartość odstająca ma tendencję do przeszacowywania współczynnika.

Dobrym rozwiązaniem tego problemu jest standaryzacja zmiennej. Standaryzacja oznacza odchylenie standardowe równe jeden i średnią zerową. Proces normalizacji składa się z dwóch etapów. Przede wszystkim odejmuje średnią wartość zmiennej. Po drugie, dzieli się przez odchylenie standardowe, tak że rozkład ma jednostkowe odchylenie standardowe.

Biblioteka sklearn jest pomocna przy standaryzacji zmiennych. Można w tym celu wykorzystać moduł wstępnego przetwarzania ze skalą obiektu.

Możesz użyć poniższej funkcji, aby skalować zbiór danych. Pamiętaj, że nie skalujesz kolumny etykiety ani zmiennych kategorialnych.

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

Możesz użyć tej funkcji do skonstruowania skalowanego zestawu pociągowego/testowego.

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

Podstawowa regresja: benchmark

Po pierwsze, trenujesz i testujesz model bez interakcji. Celem jest sprawdzenie metryki wydajności modelu.

Sposób uczenia modelu jest dokładnie taki sam, jak w samouczku Interfejs API wysokiego poziomu. Będziesz używać estymatora LinearRegressor TensorFlow.

Dla przypomnienia należy wybrać:

  • cechy, które należy umieścić w modelu
  • przekształcić cechy
  • skonstruuj regresor liniowy
  • skonstruuj funkcję input_fn
  • trenować modelkę
  • przetestuj model

Do uczenia modelu używasz wszystkich zmiennych ze zbioru danych. W sumie istnieją zmienne ciągłe elevel i jedna zmienna kategoryczna

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

Konwertujesz obiekty na kolumnę liczbową lub kolumnę kategorialną

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

Tworzysz model za pomocą linearRegressor. Przechowujesz model w folderze train_Boston

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

Wydajność

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}

Każda kolumna w danych pociągowych lub testowych jest konwertowana na tensor za pomocą funkcji 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)

Oszacowujesz model na podstawie danych pociągu.

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

Wydajność

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>

Na koniec szacujesz wydajność modelu na zestawie testowym

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

Wydajność

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}

Strata modelu wynosi 1650. Jest to metryka do pobicia w następnej sekcji

Ulepsz model: Termin interakcji

W pierwszej części samouczka zobaczyłeś interesującą relację między zmiennymi. Różne techniki wizualizacji ujawniły, że INDUS i NOS są ze sobą powiązane i zmieniają się, aby zwiększyć wpływ na cenę. Nie tylko interakcja między INDUS i NOS wpływa na cenę, ale również ten efekt jest silniejszy, gdy oddziałuje z DIS.

Nadszedł czas, aby uogólnić tę koncepcję i sprawdzić, czy można ulepszyć model przewidywany przez model.

Musisz dodać dwie nowe kolumny do każdego zestawu danych: pociąg + test. W tym celu tworzysz jedną funkcję do obliczania składnika interakcji i drugą do obliczania potrójnego składnika interakcji. Każda funkcja tworzy pojedynczą kolumnę. Po utworzeniu nowych zmiennych można je połączyć ze zbiorem danych szkoleniowym i testowym.

Przede wszystkim należy utworzyć nową zmienną dla interakcji pomiędzy INDUS i NOX.

Poniższa funkcja zwraca dwie ramki danych, pociąg i test, z interakcją między var_1 i var_2, w twoim przypadku INDUS i 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

Przechowujesz dwie nowe kolumny

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

Po drugie, tworzysz drugą funkcję, aby obliczyć termin potrójnej interakcji.

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

Teraz, gdy masz już wszystkie potrzebne kolumny, możesz je dodać do uczenia i testowania zbioru danych. Nazywasz te dwie nowe ramki danych:

  • df_train_nowy
  • df_test_nowy
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)

Wydajność

Popraw termin interakcji modelu

To jest to; możesz oszacować nowy model za pomocą warunków interakcji i zobaczyć, jak wygląda metryka wydajności.

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)

Wydajność

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}

KOD

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)

Wydajność

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)

Wydajność

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}

Nowa strata wynosi 1515. Dodanie dwóch nowych zmiennych pozwoliło zmniejszyć stratę. Oznacza to, że możesz dokonać lepszych prognoz niż w przypadku modelu porównawczego.