Zbuduj model liniowy za pomocą estymatorów

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

Przegląd

Ten kompleksowy przewodnik szkoli model regresji logistycznej przy użyciu interfejsu API tf.estimator . Model jest często używany jako punkt odniesienia dla innych, bardziej złożonych algorytmów.

Ustawiać

pip install sklearn
import os
import sys

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

Załaduj tytaniczny zbiór danych

Użyjesz zestawu danych Titanica w (raczej chorobliwym) celu przewidywania przeżycia pasażerów, z uwzględnieniem określonych cech, takich jak płeć, wiek, klasa itp.

import tensorflow.compat.v2.feature_column as fc

import tensorflow as tf
# 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')

Przeglądaj dane

Zbiór danych zawiera następujące funkcje

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)
<AxesSubplot:>

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

png

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

dftrain['class'].value_counts().plot(kind='barh')
<AxesSubplot:>

png

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

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

png

Inżynieria funkcji dla modelu

Estymatory używają systemu zwanego kolumnami funkcji, aby opisać, jak model powinien interpretować każdą z surowych funkcji wejściowych. Estymator oczekuje wektora danych wejściowych liczbowych, a kolumny funkcji opisują, jak model powinien konwertować każdą funkcję.

Wybór i tworzenie odpowiedniego zestawu kolumn funkcji jest kluczem do nauki skutecznego modelu. Kolumna elementów może być albo jednym z nieprzetworzonych danych wejściowych w oryginalnych dict ( kolumna elementów podstawowych ), albo dowolnymi nowymi kolumnami utworzonymi przy użyciu przekształceń zdefiniowanych w jednej lub wielu kolumnach podstawowych (kolumny elementów pochodnych ).

Estymator liniowy wykorzystuje 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ą one pewne możliwości inżynierii funkcji, takie jak jednokrotne kodowanie, normalizacja i zasobniki.

Kolumny funkcji podstawowych

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

feature_columns = []
for feature_name in CATEGORICAL_COLUMNS:
  vocabulary = dftrain[feature_name].unique()
  feature_columns.append(tf.feature_column.categorical_column_with_vocabulary_list(feature_name, vocabulary))

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

Funkcja input_function określa sposób konwersji danych do tf.data.Dataset , który zasila potok wejściowy w sposób przesyłania strumieniowego. tf.data.Dataset może przyjmować wiele źródeł, takich jak dataframe, plik w formacie csv i inne.

def make_input_fn(data_df, label_df, num_epochs=10, shuffle=True, batch_size=32):
  def input_function():
    ds = tf.data.Dataset.from_tensor_slices((dict(data_df), label_df))
    if shuffle:
      ds = ds.shuffle(1000)
    ds = ds.batch(batch_size).repeat(num_epochs)
    return ds
  return input_function

train_input_fn = make_input_fn(dftrain, y_train)
eval_input_fn = make_input_fn(dfeval, y_eval, num_epochs=1, shuffle=False)

Możesz sprawdzić zbiór danych:

ds = make_input_fn(dftrain, y_train, batch_size=10)()
for feature_batch, label_batch in ds.take(1):
  print('Some feature keys:', list(feature_batch.keys()))
  print()
  print('A batch of class:', feature_batch['class'].numpy())
  print()
  print('A batch of Labels:', label_batch.numpy())
Some feature keys: ['sex', 'age', 'n_siblings_spouses', 'parch', 'fare', 'class', 'deck', 'embark_town', 'alone']

A batch of class: [b'Third' b'Third' b'Third' b'Third' b'Third' b'First' b'Second' b'First'
 b'First' b'Third']

A batch of Labels: [0 1 1 0 0 1 0 1 1 0]

Możesz również sprawdzić wynik określonej kolumny funkcji, korzystając z warstwy tf.keras.layers.DenseFeatures :

age_column = feature_columns[7]
tf.keras.layers.DenseFeatures([age_column])(feature_batch).numpy()
array([[35.],
       [14.],
       [28.],
       [19.],
       [28.],
       [35.],
       [60.],
       [63.],
       [45.],
       [21.]], dtype=float32)

DenseFeatures akceptuje tylko gęste tensory, aby sprawdzić kolumnę kategorii, musisz najpierw przekształcić ją w kolumnę wskaźnika:

gender_column = feature_columns[0]
tf.keras.layers.DenseFeatures([tf.feature_column.indicator_column(gender_column)])(feature_batch).numpy()
array([[1., 0.],
       [0., 1.],
       [0., 1.],
       [1., 0.],
       [1., 0.],
       [1., 0.],
       [1., 0.],
       [0., 1.],
       [0., 1.],
       [0., 1.]], dtype=float32)

Po dodaniu wszystkich podstawowych funkcji do modelu, przeszkolmy model. Trenowanie modelu to tylko jedno polecenie przy użyciu API tf.estimator :

linear_est = tf.estimator.LinearClassifier(feature_columns=feature_columns)
linear_est.train(train_input_fn)
result = linear_est.evaluate(eval_input_fn)

clear_output()
print(result)
{'accuracy': 0.7537879, 'accuracy_baseline': 0.625, 'auc': 0.8060607, 'auc_precision_recall': 0.7480768, 'average_loss': 0.5639972, 'label/mean': 0.375, 'loss': 0.5542658, 'precision': 0.7741935, 'prediction/mean': 0.25232768, 'recall': 0.4848485, 'global_step': 200}

Kolumny funkcji pochodnych

Teraz osiągnąłeś dokładność 75%. Użycie każdej kolumny cech podstawowych oddzielnie może nie wystarczyć do wyjaśnienia danych. Na przykład korelacja między wiekiem a etykietą może być różna dla różnych płci. Dlatego, jeśli poznasz tylko jedną wagę modelu dla gender="Male" i gender="Female" , nie uchwycisz wszystkich kombinacji wiek-płeć (np. rozróżniając gender="Male" AND age="30" AND gender="Male" ORAZ age="40" ).

Aby poznać różnice między różnymi kombinacjami funkcji, możesz dodać do modelu kolumny funkcji krzyżujących się (możesz także podzielić kolumnę wieku przed kolumną krzyżową):

age_x_gender = tf.feature_column.crossed_column(['age', 'sex'], hash_bucket_size=100)

Po dodaniu funkcji kombinacji do modelu, przeszkolmy model ponownie:

derived_feature_columns = [age_x_gender]
linear_est = tf.estimator.LinearClassifier(feature_columns=feature_columns+derived_feature_columns)
linear_est.train(train_input_fn)
result = linear_est.evaluate(eval_input_fn)

clear_output()
print(result)
{'accuracy': 0.7462121, 'accuracy_baseline': 0.625, 'auc': 0.845577, 'auc_precision_recall': 0.7873878, 'average_loss': 0.47313985, 'label/mean': 0.375, 'loss': 0.46722567, 'precision': 0.6509434, 'prediction/mean': 0.41550797, 'recall': 0.6969697, 'global_step': 200}

Osiąga teraz dokładność 77,6%, co jest nieco lepszą wartością niż tylko wytrenowana w podstawowych funkcjach. Możesz spróbować użyć większej liczby funkcji i przekształceń, aby zobaczyć, czy możesz zrobić to lepiej!

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 został zdefiniowany przy użyciu całego zestawu ewaluacyjnego.

pred_dicts = list(linear_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')
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from /tmp/tmpe5vngw46/model.ckpt-200
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
<AxesSubplot:title={'center':'predicted probabilities'}, ylabel='Frequency'>

png

Na koniec spójrz na charakterystykę działania odbiornika (ROC) wyników, która da nam lepsze wyobrażenie o kompromisie między stawką prawdziwie pozytywnych a stawką fałszywie pozytywnych.

from sklearn.metrics import roc_curve
from matplotlib import pyplot as plt

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,)
(0.0, 1.05)

png