Pomoc chronić Wielkiej Rafy Koralowej z TensorFlow na Kaggle Dołącz Wyzwanie

Wzmocnione drzewa za pomocą estymatorów

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło na GitHub Pobierz notatnik

Ten samouczek to kompleksowy przewodnik dotyczący uczenia modelu Gradient Boosting przy użyciu drzew decyzyjnych z interfejsem API tf.estimator . Modele Boosted Trees należą do najpopularniejszych i najskuteczniejszych podejść do uczenia maszynowego zarówno w przypadku regresji, jak i klasyfikacji. Jest to technika zespołowa, która łączy przewidywania z kilku (pomyśl 10, 100, a nawet 1000) modeli drzewa.

Modele Boosted Trees są popularne wśród wielu praktyków uczenia maszynowego, ponieważ mogą osiągnąć imponującą wydajność przy minimalnym dostrajaniu hiperparametrów.

Załaduj tytaniczny zbiór danych

Będziesz korzystać z tytanicznego zbioru danych, w którym (raczej chorobliwym) celem jest przewidywanie przeżycia pasażerów z uwzględnieniem określonych cech, takich jak płeć, wiek, klasa itp.

import numpy as np
import pandas as pd
from IPython.display import clear_output
from matplotlib import pyplot as plt

# Load dataset.
dftrain = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/train.csv')
dfeval = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/eval.csv')
y_train = dftrain.pop('survived')
y_eval = dfeval.pop('survived')
import tensorflow as tf
tf.random.set_seed(123)

Zestaw danych składa się z zestawu uczącego i zestawu ewaluacyjnego:

  • dftrain i y_train to zestaw uczący — dane, których model używa do uczenia się.
  • Model jest testowany z zestawami eval , dfeval i y_eval .

Do szkolenia wykorzystasz następujące funkcje:

Nazwa funkcji Opis
seks Płeć pasażera
wiek Wiek pasażera
n_rodzeństwa_małżonków rodzeństwo i partnerzy na pokładzie
spiec rodziców i dzieci na pokładzie
opłata Opłata pasażera zapłacona.
klasa Klasa pasażera na statku
talia kart Który pasażer pokładowy był na pokładzie?
embark_town Z którego miasta wsiadł pasażer?
sam Gdyby pasażer był sam

Przeglądaj dane

Najpierw obejrzyjmy niektóre dane i stwórzmy statystyki podsumowujące na zbiorze uczącym.

dftrain.head()
dftrain.describe()

W zestawach szkoleniowych i ewaluacyjnych znajduje się odpowiednio 627 i 264 przykładów.

dftrain.shape[0], dfeval.shape[0]
(627, 264)

Większość pasażerów ma 20 i 30 lat.

dftrain.age.hist(bins=20)
plt.show()

png

Na pokładzie jest około dwa razy więcej pasażerów płci męskiej niż kobiet.

dftrain.sex.value_counts().plot(kind='barh')
plt.show()

png

Większość pasażerów znajdowała się w „trzeciej” klasie.

dftrain['class'].value_counts().plot(kind='barh')
plt.show()

png

Większość pasażerów wsiadała z Southampton.

dftrain['embark_town'].value_counts().plot(kind='barh')
plt.show()

png

Kobiety mają znacznie większą szansę na przeżycie niż mężczyźni. Będzie to wyraźnie funkcja predykcyjna dla modelu.

pd.concat([dftrain, y_train], axis=1).groupby('sex').survived.mean().plot(kind='barh').set_xlabel('% survive')
plt.show()

png

Twórz kolumny funkcji i funkcje wprowadzania

Estymator Gradient Boosting może wykorzystywać zarówno cechy liczbowe, jak i kategoryczne. Kolumny funkcji współpracują ze wszystkimi estymatorami TensorFlow, a ich celem jest zdefiniowanie funkcji używanych do modelowania. Ponadto zapewniają pewne możliwości inżynierii funkcji, takie jak jednokrotne kodowanie na gorąco, normalizacja i zasobniki. W tym samouczku pola w kolumnach CATEGORICAL_COLUMNS są przekształcane z kolumn kategorialnych do kolumn zakodowanych na gorąco ( kolumna wskaźnika ):

CATEGORICAL_COLUMNS = ['sex', 'n_siblings_spouses', 'parch', 'class', 'deck',
                       'embark_town', 'alone']
NUMERIC_COLUMNS = ['age', 'fare']

def one_hot_cat_column(feature_name, vocab):
  return tf.feature_column.indicator_column(
      tf.feature_column.categorical_column_with_vocabulary_list(feature_name,
                                                 vocab))
feature_columns = []
for feature_name in CATEGORICAL_COLUMNS:
  # Need to one-hot encode categorical features.
  vocabulary = dftrain[feature_name].unique()
  feature_columns.append(one_hot_cat_column(feature_name, vocabulary))

for feature_name in NUMERIC_COLUMNS:
  feature_columns.append(tf.feature_column.numeric_column(feature_name,
                                           dtype=tf.float32))

Możesz zobaczyć przekształcenie, które tworzy kolumna funkcji. Na przykład, oto dane wyjściowe, gdy używasz indicator_column na pojedynczym przykładzie:

example = dict(dftrain.head(1))
class_fc = tf.feature_column.indicator_column(tf.feature_column.categorical_column_with_vocabulary_list('class', ('First', 'Second', 'Third')))
print('Feature value: "{}"'.format(example['class'].iloc[0]))
print('One-hot encoded: ', tf.keras.layers.DenseFeatures([class_fc])(example).numpy())
Feature value: "Third"
One-hot encoded:  [[0. 0. 1.]]

Dodatkowo możesz wyświetlić wszystkie przekształcenia kolumn funkcji razem:

tf.keras.layers.DenseFeatures(feature_columns)(example).numpy()
array([[22.  ,  1.  ,  0.  ,  1.  ,  0.  ,  0.  ,  1.  ,  0.  ,  0.  ,

         0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  1.  ,  0.  ,  0.  ,  0.  ,
         7.25,  1.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  1.  ,
         0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  1.  ,  0.  ]], dtype=float32)

Następnie musisz utworzyć funkcje wejściowe. Określają one, w jaki sposób dane będą wczytywane do naszego modelu zarówno w celu uczenia, jak i wnioskowania. Użyjesz metody from_tensor_slices w interfejsie API tf.data , aby wczytać dane bezpośrednio z Pand. Jest to odpowiednie dla mniejszych zestawów danych w pamięci. W przypadku większych zestawów danych interfejs API tf.data obsługuje różne formaty plików (w tym csv ), dzięki czemu można przetwarzać zestawy danych, które nie mieszczą się w pamięci.

# Use entire batch since this is such a small dataset.
NUM_EXAMPLES = len(y_train)

def make_input_fn(X, y, n_epochs=None, shuffle=True):
  def input_fn():
    dataset = tf.data.Dataset.from_tensor_slices((dict(X), y))
    if shuffle:
      dataset = dataset.shuffle(NUM_EXAMPLES)
    # For training, cycle thru dataset as many times as need (n_epochs=None).
    dataset = dataset.repeat(n_epochs)
    # In memory training doesn't use batching.
    dataset = dataset.batch(NUM_EXAMPLES)
    return dataset
  return input_fn

# Training and evaluation input functions.
train_input_fn = make_input_fn(dftrain, y_train)
eval_input_fn = make_input_fn(dfeval, y_eval, shuffle=False, n_epochs=1)

Trenuj i oceniaj model

Poniżej wykonasz następujące kroki:

  1. Zainicjuj model, określając cechy i hiperparametry.
  2. Podaj dane szkoleniowe do modelu za pomocą train_input_fn i trenuj model za pomocą funkcji train .
  3. Ocenisz wydajność modelu za pomocą zestawu ewaluacyjnego — w tym przykładzie dfeval DataFrame. Zweryfikujesz, czy przewidywania pasują do etykiet z tablicy y_eval .

Przed uczeniem modelu drzew wzmocnionych najpierw nauczmy klasyfikatora liniowego (model regresji logistycznej). Najlepszą praktyką jest rozpoczęcie od prostszego modelu w celu ustalenia punktu odniesienia.

linear_est = tf.estimator.LinearClassifier(feature_columns)

# Train model.
linear_est.train(train_input_fn, max_steps=100)

# Evaluation.
result = linear_est.evaluate(eval_input_fn)
clear_output()
print(pd.Series(result))
accuracy                  0.765152
accuracy_baseline         0.625000
auc                       0.832844
auc_precision_recall      0.789631
average_loss              0.478908
label/mean                0.375000
loss                      0.478908
precision                 0.703297
prediction/mean           0.350790
recall                    0.646465
global_step             100.000000
dtype: float64

Następnie nauczmy model drzew wzmocnionych. W przypadku drzew wzmocnionych obsługiwana jest regresja ( BoostedTreesRegressor ) i klasyfikacja ( BoostedTreesClassifier ). Ponieważ celem jest przewidzenie klasy - przetrwa lub nie przetrwa, użyjesz BoostedTreesClassifier .

# Since data fits into memory, use entire dataset per layer. It will be faster.
# Above one batch is defined as the entire dataset.
n_batches = 1
est = tf.estimator.BoostedTreesClassifier(feature_columns,
                                          n_batches_per_layer=n_batches)

# The model will stop training once the specified number of trees is built, not
# based on the number of steps.
est.train(train_input_fn, max_steps=100)

# Eval.
result = est.evaluate(eval_input_fn)
clear_output()
print(pd.Series(result))
accuracy                  0.837121
accuracy_baseline         0.625000
auc                       0.871993
auc_precision_recall      0.858760
average_loss              0.406563
label/mean                0.375000
loss                      0.406563
precision                 0.797872
prediction/mean           0.384452
recall                    0.757576
global_step             100.000000
dtype: float64

Teraz możesz użyć modelu pociągu do prognozowania pasażera z zestawu ewaluacyjnego. Modele TensorFlow są zoptymalizowane pod kątem prognozowania partii lub kolekcji przykładów naraz. Wcześniej eval_input_fn jest definiowany przy użyciu całego zestawu ewaluacyjnego.

pred_dicts = list(est.predict(eval_input_fn))
probs = pd.Series([pred['probabilities'][1] for pred in pred_dicts])

probs.plot(kind='hist', bins=20, title='predicted probabilities')
plt.show()
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from /tmp/tmp98s7_n3y/model.ckpt-100
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
Exception ignored in: <function CapturableResource.__del__ at 0x7ff2fb5bd950>
Traceback (most recent call last):
  File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/training/tracking/tracking.py", line 269, in __del__
    with self._destruction_context():
AttributeError: 'TreeEnsemble' object has no attribute '_destruction_context'

png

Na koniec możesz również spojrzeć na charakterystykę działania odbiornika (ROC) wyników, która da nam lepsze pojęcie o kompromisie między stawką prawdziwie pozytywnych a stawką fałszywie pozytywnych.

from sklearn.metrics import roc_curve

fpr, tpr, _ = roc_curve(y_eval, probs)
plt.plot(fpr, tpr)
plt.title('ROC curve')
plt.xlabel('false positive rate')
plt.ylabel('true positive rate')
plt.xlim(0,)
plt.ylim(0,)
plt.show()

png