Erstellen Sie ein lineares Modell mit Schätzern

Auf TensorFlow.org ansehen In Google Colab ausführen Quelle auf GitHub anzeigen Notizbuch herunterladen

Überblick

Diese tf.estimator exemplarische tf.estimator trainiert ein logistisches Regressionsmodell mit der tf.estimator API. Das Modell wird oft als Basis für andere, komplexere Algorithmen verwendet.

Einrichten

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

Laden Sie den Titanic-Datensatz

Sie verwenden den Titanic-Datensatz mit dem (eher morbiden) Ziel, das Überleben der Passagiere anhand von Merkmalen wie Geschlecht, Alter, Klasse usw. vorherzusagen.

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

Erkunden Sie die Daten

Der Datensatz enthält die folgenden Funktionen

dftrain.head()
dftrain.describe()

Es gibt 627 bzw. 264 Beispiele in den Trainings- und Evaluierungssets.

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

Die meisten Passagiere sind zwischen 20 und 30 Jahre alt.

dftrain.age.hist(bins=20)
<AxesSubplot:>

png

An Bord befinden sich etwa doppelt so viele männliche Passagiere wie weibliche Passagiere.

dftrain.sex.value_counts().plot(kind='barh')
<AxesSubplot:>

png

Die Mehrheit der Passagiere befand sich in der "dritten" Klasse.

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

png

Frauen haben eine viel höhere Überlebenschance als Männer. Dies ist eindeutig ein prädiktives Merkmal für das Modell.

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

png

Feature Engineering für das Modell

Schätzer verwenden ein System namens Feature-Spalten, um zu beschreiben, wie das Modell jedes der rohen Eingabe-Features interpretieren soll. Ein Estimator erwartet einen Vektor numerischer Eingaben, und Feature-Spalten beschreiben, wie das Modell jedes Feature umwandeln soll.

Die Auswahl und Erstellung des richtigen Satzes von Feature-Spalten ist der Schlüssel zum Erlernen eines effektiven Modells. Eine Feature-Spalte kann entweder eine der Roheingaben im ursprünglichen Feature- dict (eine Basis-Feature-Spalte ) oder jede neue Spalte sein, die mit Transformationen erstellt wurde, die über eine oder mehrere Basisspalten definiert wurden (eine abgeleitete Feature-Spalte ).

Der lineare Schätzer verwendet sowohl numerische als auch kategoriale Merkmale. Feature-Spalten funktionieren mit allen TensorFlow-Schätzern und ihr Zweck besteht darin, die für die Modellierung verwendeten Features zu definieren. Darüber hinaus bieten sie einige Feature-Engineering-Funktionen wie One-Hot-Encoding, Normalisierung und Bucketization.

Basisfunktionsspalten

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

Die input_function gibt an, wie Daten in eintf.data.Dataset konvertiert werden, das die Eingabepipeline auf Streaming-Art speist.tf.data.Dataset kann mehrere Quellen aufnehmen, z. B. einen Datenrahmen, eine csv-formatierte Datei und mehr.

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)

Sie können den Datensatz überprüfen:

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'Second' b'Third' b'First' b'First' b'Third' b'Third'
 b'Third' b'Third']

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

Sie können das Ergebnis einer bestimmten Feature-Spalte auch mit dem Layer tf.keras.layers.DenseFeatures :

age_column = feature_columns[7]
tf.keras.layers.DenseFeatures([age_column])(feature_batch).numpy()
array([[ 9.  ],
       [24.  ],
       [23.  ],
       [28.  ],
       [24.  ],
       [40.  ],
       [31.  ],
       [36.  ],
       [28.  ],
       [ 0.75]], dtype=float32)

DenseFeatures akzeptiert nur dichte Tensoren. DenseFeatures eine kategoriale Spalte zu untersuchen, müssen Sie diese zuerst in eine Indikatorspalte umwandeln:

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

Nachdem Sie dem Modell alle Basis-Features hinzugefügt haben, trainieren wir das Modell. Das Trainieren eines Modells ist nur ein einzelner Befehl mit der tf.estimator API:

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.74242425, 'accuracy_baseline': 0.625, 'auc': 0.83409864, 'auc_precision_recall': 0.79196465, 'average_loss': 0.48227197, 'label/mean': 0.375, 'loss': 0.47621801, 'precision': 0.64761907, 'prediction/mean': 0.4210519, 'recall': 0.68686867, 'global_step': 200}

Abgeleitete Feature-Spalten

Jetzt haben Sie eine Genauigkeit von 75% erreicht. Die separate Verwendung jeder Basis-Feature-Spalte reicht möglicherweise nicht aus, um die Daten zu erklären. Beispielsweise kann die Korrelation zwischen Alter und Etikett für verschiedene Geschlechter unterschiedlich sein. Wenn Sie also nur eine einzelne Modellgewichtung für gender="Male" und gender="Female" lernen, erfassen Sie nicht jede Alters-Geschlecht-Kombination (z. B. die Unterscheidung zwischen gender="Male" AND age="30" AND gender="Male" UND age="40" ).

Um die Unterschiede zwischen verschiedenen Feature-Kombinationen zu erfahren, können Sie dem Modell gekreuzte Feature-Spalten hinzufügen (Sie können auch die Altersspalte vor der Kreuzspalte in Buckets einteilen):

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

Nachdem wir dem Modell das Kombinations-Feature hinzugefügt haben, trainieren wir das Modell erneut:

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.7689394, 'accuracy_baseline': 0.625, 'auc': 0.8474442, 'auc_precision_recall': 0.7786934, 'average_loss': 0.4796637, 'label/mean': 0.375, 'loss': 0.47112098, 'precision': 0.73170733, 'prediction/mean': 0.3178967, 'recall': 0.6060606, 'global_step': 200}

Es erreicht jetzt eine Genauigkeit von 77,6%, was etwas besser ist als nur in Basisfunktionen trainiert. Sie können versuchen, weitere Funktionen und Transformationen zu verwenden, um zu sehen, ob Sie es besser machen können!

Jetzt können Sie das Zugmodell verwenden, um Vorhersagen zu einem Fahrgast aus dem Bewertungsset zu treffen. TensorFlow-Modelle sind optimiert, um Vorhersagen für einen Batch oder eine Sammlung von Beispielen gleichzeitig zu treffen. Früher wurde eval_input_fn mit dem gesamten Auswertungssatz definiert.

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/tmpoq0ukjec/model.ckpt-200
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
<AxesSubplot:title={'center':'predicted probabilities'}, ylabel='Frequency'>

png

Betrachten Sie schließlich die Receiver Operating Characteristic (ROC) der Ergebnisse, die uns eine bessere Vorstellung vom Kompromiss zwischen der True-Positive-Rate und der False-Positive-Rate geben.

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