Regresja liniowa TensorFlow z aspektem i terminem interakcji

⚡ Inteligentne podsumowanie

Regresja liniowa danych dotyczących rynku nieruchomości w Bostonie staje się skuteczniejsza, gdy najpierw zostaną znalezione właściwe wyrazy interakcji. Google Funkcja Facets uwidacznia te zależności wizualnie, a dwie skrzyżowane funkcje zmniejszyły stratę testu TensorFlow z 1650 do 1515.

  • 🔘 Najpierw dane: Zrozumienie rozkładów i wartości odstających jest niezbędne, aby zbudować jakikolwiek model, ponieważ model uogólnia jedynie wzorzec, który już zlokalizowałeś.
  • ️ Przegląd aspektów: Statystyki dla każdej funkcji ujawniają brakujące wartości, kolumny z dużą liczbą zer i dryft rozkładu „uczenie kontra test” w jednej tabeli.
  • ✅ Głębokie zanurzenie w Facets: Fasetowanie według X i Y przekształca relacje trójstronne w czytelny wykres 2D pokolorowany według kwartyli cenowych.
  • 🧪 Odczyt korelacyjny: Mapa cieplna i siatka par oznaczają INDUS z NOX, a DIS z obydwoma, jako kandydatów do interakcji.
  • 🛠️. Normalizacja: preprocessing.scale centruje dwanaście ciągłych kolumn zanim estymator je zobaczy, pozostawiając CHAS i PRICE nietknięte.
  • 📈 Zmierzony zysk: Dodanie INDUS_NOS i INDUS_NOS_DIS powoduje, że średnia strata podczas testu podziału zmienia się z 86.89361 na 79.78876.

Regresja liniowa TensorFlow z fasetą i członem interakcji

Regresja liniowa TensorFlow

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 OPIS
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.

Interakcja między wykształceniem a zawodem zilustrowana na krzywej płac

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

Równanie płac rozszerzone o interakcję wykształcenia i zawodu

If Symbol współczynnika beta dla członu 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.

Ta sama rodzina estymatorów zasila również klasyfikator liniowy gdy etykieta jest klasą, a nie ceną. W tym samouczku postaramy się sprawdzić, które zmienne mogą być dobrymi kandydatami na terminy interakcji. Przetestujemy, czy dodanie tego rodzaju informacji prowadzi do lepszego przewidywania ceny.

Statystyki podsumowujące

Przed przystąpieniem do tworzenia modelu należy wykonać kilka kroków. Jak wspomniano wcześniej, model stanowi uogólnienie danych. Najlepszą praktyką jest najpierw zrozumieć dane, a dopiero potem formułować prognozy. Jeśli nie znasz swoich danych, szanse na ulepszenie modelu są nikłe.

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

Wskazówki: W tym samouczku musisz mieć zainstalowane biblioteki matplotlib 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 PythonSeaborn to biblioteka do wizualizacji statystycznej oparta na bibliotece matplotlib. Zapewnia ona:tracatrakcyjne 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.

Uwaga dotycząca wersji: load_boston zostało uznane za przestarzałe w scikit-learn 1.0 i usunięto w scikit-learn 1.2 ponieważ zbiór danych koduje funkcję o charakterze rasowym. W bieżącej instalacji użyj pobierz_mieszkania_w_kalifornii Zamiast tego możesz samodzielnie załadować plik RAW. Przepływ pracy pokazany poniżej pozostaje niezmieniony; różni się tylko moduł ładujący.

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

Nazwy funkcji są przechowywane w obiekcie feature_names jako tablica.

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)

Pierwsze dwa wiersze ramki danych Boston DataFrame po zmianie nazw kolumn

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 posiada wbudowaną funkcję próbkowania umożliwiającą podział 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 naprawia tasowanie, dzięki czemu dla wszystkich zwracane są te same wiersze.

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

Google Zespół badawczy opracował narzędzie do tego zadania o nazwie Fasety Pomaga to wizualizować dane i dzielić je na różne sposoby. To dobry punkt wyjścia do zrozumienia, jak zbudowany jest zbiór danych.

Funkcja Facets umożliwia znalezienie sytuacji, w których dane nie wyglądają tak, jak się spodziewałeś.

Z wyjątkiem ich aplikacji internetowej, Google ułatwia osadzanie zestawu narzędzi w 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 świetne narzędzie. Pozwala uzyskać pewien poziom przejrzystości w zbiorze danych i maksymalnie powiększyć go, aby zobaczyć pojedynczy fragment. Oznacza to, że możesz analizować dane według wiersza i kolumny w obrębie dowolnych cech zbioru 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.

Zanim będzie można użyć któregokolwiek z narzędzi, należy zainstalować Facets w środowisku notebooka.

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żeli na Twoim komputerze nie ma zainstalowanego Gita, przejdź tutaj URL Git dla Windows pobrać stronę 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 repozytorium kodu PAIR/aspektów i pobierz repozytoria.

Strona repozytorium aspektów kodu PAIR na GitHubie

Na stronie repozytorium powyżej znajduje się przycisk pobierania używany w opcji 2. Jeśli wybierzesz pierwszą opcję, plik trafi do folderu pobierania. Możesz pozwolić plikowi na pobranie lub przeciągnąć go do innej ścieżki.

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.

Terminal pokazujący folder facetów w bieżącym katalogu roboczym

Powyższy opis terminala potwierdza, że ​​facets znajduje się w bieżącym katalogu roboczym. Musisz wskazać katalog roboczy 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:

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.

Przegląd aspektów uruchomienia w Jupyter

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ę

Ścieżka pliku do folderu Python facets_overview

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ć:

Tabela przeglądu aspektów zawierająca statystyki podsumowujące dla każdej funkcji

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

Wykres korelacji i siatka par

Po sprawdzeniu danych i ich rozkładu można sporządzić macierz korelacji. Macierz korelacji oblicza współczynnik Pearsona. Współczynnik ten mieści się w przedziale od -1 do 1, gdzie wartość dodatnia oznacza korelację dodatnią, a wartość ujemna – korelację ujemną.

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

Uwaga dotycząca wersji: maska ​​poniżej wzywa np.bool, alias, który został uznany za przestarzały w NumPy 1.20 i usunięto w NumPy 1.24. W ostatnim NumPy ta sama linia powoduje AttributeError: module 'numpy' has no attribute 'bool'; wbudowany bool jest zamiennikiem typu drop-in.

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

Mapa cieplna korelacji Seaborna zmiennych bostońskich

Na powyższej mapie cieplnej ciemniejsze kwadraty oznaczają silniejsze korelacje. Z macierzy widać:

  • LSTAT
  • RM

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

Masz pierwszą wskazówkę, że INDUS i NOX mogą być dobrymi kandydatami na człon interakcyjny, a DIS może być również interesującym tematem do skupienia się na nim.

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

Siatka par składa się z następujących elementów:

  • 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

Skupiasz się na czterech zmiennych niezależnych. Wybór dotyczy zmiennych silnie skorelowanych z CENĄ.

  • 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ść

Siatka par Seaborn PRICE, INDUS, NOX, RM i LSTAT

Zacznijmy od górnej części:

  • Cena jest ujemnie skorelowana z INDUS, NOX i LSTAT; dodatnio skorelowane z RM.
  • Istnieje niewielka nieliniowość pomiędzy LSTAT i PRICE
  • 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 skorzystać z drugiego narzędzia stworzonego przez Google, Facets Deep Dive. Interfejs jest podzielony na cztery główne sekcje. Obszar centralny to powiększalny widok danych. W górnej części panelu znajduje się menu rozwijane, w którym można zmieniać układ danych, sterować fasetowaniem, pozycjonowaniem i kolorem. Po prawej stronie znajduje się szczegółowy widok konkretnego wiersza danych. Oznacza to, że można kliknąć dowolny punkt danych w centralnej wizualizacji, aby wyświetlić 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 utworzyć wykres 2D i pokolorować kropki. Można podzielić zmienną PRICE na cztery kategorie, z których każda będzie kwartylem (tj. 0.25, 0.5, 0.75). Tę nową zmienną nazywamy 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 punktowy DIS względem INDUS pokolorowany według kwartyla cenowego

Korzystanie z Facets Deep Dive

Aby otworzyć Deep Dive, musisz przekształcić dane do formatu JSON. Pandas ma na to metodę: wywołaj to_json w DataFrame.

Pierwszy wiersz kodu ustawia rozmiar sprite'a na podstawie liczby wierszy w zbiorze 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:

Facets Deep Dive – widok rozrzutu fasetowego zbioru danych z Bostonu

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

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

W tym przypadku ciemniejsze kolory oznaczają większą odległość do pierwszego ośrodka zatrudnienia.

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.

Eksploracja doprowadziła do wykrycia dwóch potencjalnych interakcji, zatem następnym krokiem będzie ich przetestowanie w rzeczywistym modelu.

Regresja liniowa z TensorFlow

W tej sekcji oszacujesz model regresji liniowej za pomocą TensorFlow API Estimatora. Postępuj w następujący sposób:

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

Uwaga dotycząca wersji: dotychczasowy tf-estimator pakiet został wydany w wersji finalnej wraz z TensorFlow 2.15 i nie jest już dostępny w TensorFlow 2.16 i nowszych, więc tf.estimator.LinearRegressor działa tylko na TensorFlow 1.x, chyba że dokonasz migracji do liniowego modelu Keras.

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

Dane przygotowania

W większości przypadków konieczne jest przekształcenie danych. Właśnie dlatego Przegląd Facetów jest tak fascynujący. W statystyce podsumowującej zauważyliście, że występują wartości odstające. Wartości te wpływają na szacunki, ponieważ nie przypominają analizowanej populacji. Wartości odstające zazwyczaj zaburzają wyniki. Na przykład dodatnia wartość odstająca ma tendencję do zawyżania współczynnika.

Dobrym rozwiązaniem tego problemu jest standaryzacja zmiennej. Standaryzacja oznacza odchylenie standardowe równe jeden i średnią równą zero. Proces standaryzacji obejmuje dwa etapy. Po pierwsze, poddaje siętracJest to średnia wartość zmiennej. Po drugie, jest ona dzielona przez odchylenie standardowe, tak aby rozkład miał jednostkowe odchylenie standardowe.

Biblioteka nauka-scikit Przydatne do standaryzacji zmiennych. W tym celu można użyć modułu preprocessing 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 trenowania modelu jest dokładnie taki sam, jak w samouczku 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 trenowania modelu wykorzystujesz wszystkie zmienne w zbiorze danych. Łącznie jest dwanaście zmiennych ciągłych i jedna zmienna kategorialna.

## 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ągu lub testu 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.9785. Jest to metryka do pobicia w następnej sekcji

Ulepsz model: Termin interakcji

W pierwszej części samouczka dostrzegłeś interesującą zależność między zmiennymi. Różne techniki wizualizacji ujawniły, że zmienne INDUS i NOX są ze sobą powiązane i wzajemnie wzmacniają swój wpływ na cenę. Interakcja między zmiennymi INDUS i NOX nie tylko wpływa na cenę, ale efekt ten jest silniejszy, gdy zmienna ta oddziałuje ze zmienną DIS.

Czas uogólnić tę ideę i sprawdzić, czy można udoskonalić prognozę modelu.

Musisz dodać dwie nowe kolumny do każdego zbioru danych: trenującą i testującą. W tym celu utwórz jedną funkcję do obliczania członu interakcji i drugą do obliczania członu potrójnej interakcji. Każda funkcja generuje pojedynczą kolumnę. Po utworzeniu nowych zmiennych możesz je połączyć ze zbiorem danych treningowych i testowych.

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ść

DataFrame treningowy z dołączonymi kolumnami INDUS_NOS i INDUS_NOS_DIS

To wszystko: możesz oszacować nowy model za pomocą warunków interakcji i zobaczyć, jaka jest 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}

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)

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.9863. Dodanie dwóch nowych zmiennych pozwoliło zmniejszyć stratę. Oznacza to, że możesz dokonać lepszych prognoz niż w przypadku modelu porównawczego.

Model Zestaw funkcji Katalog modeli średnia_strata od
Benchmark 12 znormalizowanych kolumn ciągłych plus CHAS pociąg_Boston 86.89361 1650.9785
Z interakcją Benchmark plus INDUS_NOS i INDUS_NOS_DIS pociąg_Boston_1 79.78876 1515.9863

Obie liczby pochodzą z tego samego testu podziału 101 wierszy, więc spadek średniej straty o około 8 procent można przypisać wyłącznie dwóm kolumnom interakcji.

FAQ

Został on wycofany w wersji 1.0 biblioteki scikit-learn i usunięty w wersji 1.2. Zbiór danych zawiera funkcję opartą na założeniu dotyczącym autosegregacji rasowej i cen domów, a pierwotne badanie nigdy nie potwierdziło jego założeń dotyczących jakości powietrza. Typowymi zamiennikami są nieruchomości w Kalifornii lub Ames.

Wielomian podnosi kwadrat lub sześcian jednej zmiennej, aby zakrzywić jej własną krzywą. Interakcja mnoży dwie różne zmienne, więc nachylenie jednej zależy od poziomu drugiej. W tym samouczku zbudujemy równanie drugiego rodzaju: INDUS razy NOX.

Szukaj par, które korelują ze sobą i z celem. Mapa cieplna Pearsona i siatka par robią to wizualnie; tutaj INDUS i NOX grupują się razem, a oba… track PRICE, co jest sygnałem uzasadniającym ich przekroczenie.

Zautomatyzowane biblioteki inżynierii cech generują potencjalne transformacje i krzyżowania, porównują je z wynikami dla każdej z nich i zachowują tylko te, które zmniejszają błąd. To zastępuje ręczne odczytywanie mapy cieplnej, jak pokazano tutaj, choć człowiek nadal musi sprawdzić poprawność wygenerowanych kolumn.

Copilot dobrze radzi sobie z powtarzalnymi schematami wykresów — siatki par, zamaskowane mapy cieplne, szablony HTML dla faset. Sprawdź sugerowane argumenty, ponieważ Seaborn zmienił nazwy kilku z nich, a Copilot bez problemu połączy stare i aktualne sygnatury.

Nie. Stratę należy porównywać w tym samym, odłożonym podziale, jak w tym przypadku. Strata, która występuje tylko na danych treningowych, sygnalizuje przeuczenie, a dodawanie kolumn prawie zawsze poprawia dopasowanie treningowe, niezależnie od tego, czy niosą one rzeczywiste informacje.

Maska używa np.bool, aliasu przestarzałego w NumPy 1.20 i usuniętego w wersji 1.24. Ostatnie instalacje zgłaszają błąd AttributeError. Zastąpienie wbudowanego bool pozostawia zachowanie identyczne; np.bool_ działa również, jeśli potrzebujesz typu skalarnego NumPy.

CHAS to kategoryczna flaga „tak/nie”, a PRICE to etykieta. Centrowanie i skalowanie zmiennej pozornej utrudnia odczytanie jej współczynnika bez zmiany dopasowania, a skalowanie etykiety spowodowałoby jedynie przeskalowanie zgłoszonej straty. Standaryzowane jest tylko dwanaście predyktorów ciągłych.

Podsumuj ten post następująco: