Ver en TensorFlow.org | Ejecutar en Google Colab | Ver fuente en GitHub | Descargar libreta |
Descripción general
Este tutorial completo entrena un modelo de regresión logística mediante la API tf.estimator
. El modelo se utiliza a menudo como base para otros algoritmos más complejos.
Configuración
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
Cargue el conjunto de datos titánico
Utilizará el conjunto de datos del Titanic con el objetivo (bastante morboso) de predecir la supervivencia de los pasajeros, dadas características como el sexo, la edad, la clase, etc.
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')
Explora los datos
El conjunto de datos contiene las siguientes características
dftrain.head()
dftrain.describe()
Hay 627 y 264 ejemplos en los conjuntos de entrenamiento y evaluación, respectivamente.
dftrain.shape[0], dfeval.shape[0]
(627, 264)
La mayoría de los pasajeros tienen entre 20 y 30 años.
dftrain.age.hist(bins=20)
<AxesSubplot:>
Hay aproximadamente el doble de pasajeros masculinos que de mujeres a bordo.
dftrain.sex.value_counts().plot(kind='barh')
<AxesSubplot:>
La mayoría de los pasajeros estaban en la "tercera" clase.
dftrain['class'].value_counts().plot(kind='barh')
<AxesSubplot:>
Las hembras tienen muchas más posibilidades de sobrevivir que los machos. Esta es claramente una característica predictiva del modelo.
pd.concat([dftrain, y_train], axis=1).groupby('sex').survived.mean().plot(kind='barh').set_xlabel('% survive')
Text(0.5, 0, '% survive')
Ingeniería de funciones para el modelo
Los estimadores usan un sistema llamado columnas de características para describir cómo el modelo debe interpretar cada una de las características de entrada sin procesar. Un estimador espera un vector de entradas numéricas, y las columnas de funciones describen cómo el modelo debe convertir cada función.
Seleccionar y crear el conjunto correcto de columnas de características es clave para aprender un modelo efectivo. Una columna de funciones puede ser una de las entradas sin procesar en el dict
de funciones original (una columna de funciones base ) o cualquier columna nueva creada mediante transformaciones definidas en una o varias columnas base (columnas de funciones derivadas ).
El estimador lineal utiliza características tanto numéricas como categóricas. Las columnas de características funcionan con todos los estimadores de TensorFlow y su propósito es definir las características utilizadas para el modelado. Además, brindan algunas capacidades de ingeniería de características, como codificación en caliente, normalización y segmentación.
Columnas de características base
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))
La input_function
especifica cómo se convierten los datos en un tf.data.Dataset
que alimenta la canalización de entrada en forma de transmisión. tf.data.Dataset
puede admitir múltiples fuentes, como un marco de datos, un archivo con formato csv y más.
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)
Puede inspeccionar el conjunto de datos:
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]
También puede inspeccionar el resultado de una columna de características específica utilizando la capa 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
solo acepta tensores densos, para inspeccionar una columna categórica, primero debe transformarla en una columna indicadora:
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)
Después de agregar todas las funciones base al modelo, entrenemos el modelo. Entrenar un modelo es solo un comando único usando la 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}
Columnas de funciones derivadas
Ahora alcanzaste una precisión del 75%. El uso de cada columna de características base por separado puede no ser suficiente para explicar los datos. Por ejemplo, la correlación entre la edad y la etiqueta puede ser diferente para diferentes géneros. Por lo tanto, si solo aprende un peso de modelo único para gender="Male"
y gender="Female"
, no capturará todas las combinaciones de edad y género (por ejemplo, distinguir entre gender="Male"
AND age="30"
AND gender="Male"
Y age="40"
).
Para conocer las diferencias entre las diferentes combinaciones de características, puede agregar columnas de características cruzadas al modelo (también puede clasificar la columna de edad antes de la columna cruzada):
age_x_gender = tf.feature_column.crossed_column(['age', 'sex'], hash_bucket_size=100)
Después de agregar la función de combinación al modelo, entrenemos el modelo nuevamente:
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}
Ahora logra una precisión del 77,6 %, que es ligeramente mejor que solo entrenado en funciones básicas. ¡Puede intentar usar más funciones y transformaciones para ver si puede hacerlo mejor!
Ahora puede usar el modelo de tren para hacer predicciones sobre un pasajero del conjunto de evaluación. Los modelos de TensorFlow están optimizados para hacer predicciones en un lote o colección de ejemplos a la vez. Anteriormente, eval_input_fn
se definió utilizando el conjunto de evaluación completo.
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'>
Finalmente, observe la característica operativa del receptor (ROC) de los resultados, que nos dará una mejor idea de la compensación entre la tasa de verdaderos positivos y la tasa de falsos positivos.
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)