Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Construir un modelo lineal con estimadores

Ver en TensorFlow.org Ejecutar en Google Colab Ver código fuente en GitHub Descargar cuaderno

Visión general

Este tutorial de extremo a extremo entrena un modelo de regresión logística utilizando la API tf.estimator . El modelo se usa a menudo como línea de base para otros algoritmos más complejos.

Preparar

 !pip install -q 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 Titanic con el objetivo (bastante mórbido) 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')
 

Explore los datos

El conjunto de datos contiene las siguientes características

 dftrain.head()
 
 dftrain.describe()
 

Hay 627 y 264 ejemplos en los conjuntos de capacitación 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)
 
<matplotlib.axes._subplots.AxesSubplot at 0x7fd2c8043940>

png

Hay aproximadamente el doble de pasajeros masculinos que pasajeros femeninos a bordo.

 dftrain.sex.value_counts().plot(kind='barh')
 
<matplotlib.axes._subplots.AxesSubplot at 0x7fd2c7f650f0>

png

La mayoría de los pasajeros estaban en la "tercera" clase.

 dftrain['class'].value_counts().plot(kind='barh')
 
<matplotlib.axes._subplots.AxesSubplot at 0x7fd2c7a12240>

png

Las mujeres tienen muchas más posibilidades de sobrevivir que los hombres. Esta es claramente una característica predictiva para el modelo.

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

png

Ingeniería de características 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 formato. Un Estimador espera un vector de entradas numéricas, y las columnas de características describen cómo el modelo debe convertir cada característica.

Seleccionar y crear el conjunto correcto de columnas de características es clave para aprender un modelo efectivo. Una columna de entidades puede ser una de las entradas sin procesar en el dict originales (una columna de dict base ), o cualquier columna nueva creada usando transformaciones definidas sobre una o múltiples columnas base (columnas de entidades derivadas ).

El estimador lineal utiliza características numéricas y 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, proporcionan algunas capacidades de ingeniería de características como codificación en caliente, normalización y bucketización.

Columnas de características básicas

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

input_function especifica cómo se convierten los datos en un tf.data.Dataset que alimenta la canalización de entrada de forma continua. tf.data.Dataset puede tf.data.Dataset 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'First' b'Second' b'Second' b'First' b'Third' b'Third' b'First'
 b'Second' b'First' b'Third']

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

También puede inspeccionar el resultado de una columna de entidad específica utilizando la capa tf.keras.layers.DenseFeatures :

 age_column = feature_columns[7]
tf.keras.layers.DenseFeatures([age_column])(feature_batch).numpy()
 
WARNING:tensorflow:Layer dense_features is casting an input tensor from dtype float64 to the layer's dtype of float32, which is new behavior in TensorFlow 2.  The layer has dtype float32 because its dtype defaults to floatx.

If you intended to run this layer in float32, you can safely ignore this warning. If in doubt, this warning is likely only an issue if you are porting a TensorFlow 1.X model to TensorFlow 2.

To change all layers to have dtype float64 by default, call `tf.keras.backend.set_floatx('float64')`. To change just this layer, pass dtype='float64' to the layer constructor. If you are the author of this layer, you can disable autocasting by passing autocast=False to the base Layer constructor.


array([[28.],
       [24.],
       [29.],
       [28.],
       [30.],
       [28.],
       [35.],
       [36.],
       [65.],
       [16.]], 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()
 
WARNING:tensorflow:Layer dense_features_1 is casting an input tensor from dtype float64 to the layer's dtype of float32, which is new behavior in TensorFlow 2.  The layer has dtype float32 because its dtype defaults to floatx.

If you intended to run this layer in float32, you can safely ignore this warning. If in doubt, this warning is likely only an issue if you are porting a TensorFlow 1.X model to TensorFlow 2.

To change all layers to have dtype float64 by default, call `tf.keras.backend.set_floatx('float64')`. To change just this layer, pass dtype='float64' to the layer constructor. If you are the author of this layer, you can disable autocasting by passing autocast=False to the base Layer constructor.


array([[1., 0.],
       [0., 1.],
       [1., 0.],
       [1., 0.],
       [1., 0.],
       [1., 0.],
       [0., 1.],
       [0., 1.],
       [1., 0.],
       [1., 0.]], dtype=float32)

Después de agregar todas las características básicas al modelo, entrenemos el modelo. El entrenamiento de un modelo es solo un comando 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.7651515, 'accuracy_baseline': 0.625, 'auc': 0.83388436, 'auc_precision_recall': 0.7689738, 'average_loss': 0.5131227, 'label/mean': 0.375, 'loss': 0.50400764, 'precision': 0.8032787, 'prediction/mean': 0.2769107, 'recall': 0.4949495, 'global_step': 200}

Columnas de características 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 el género y la etiqueta puede ser diferente para un género diferente. 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" Y age="30" Y 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 agrupar 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 nuevamente el modelo:

 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.7537879, 'accuracy_baseline': 0.625, 'auc': 0.84741354, 'auc_precision_recall': 0.781831, 'average_loss': 0.4654707, 'label/mean': 0.375, 'loss': 0.45669848, 'precision': 0.67, 'prediction/mean': 0.39288065, 'recall': 0.67676765, 'global_step': 200}

Ahora alcanza una precisión del 77,6%, que es ligeramente mejor que solo entrenado en características básicas. ¡Puedes intentar usar más funciones y transformaciones para ver si puedes hacerlo mejor!

Ahora puede usar el modelo de tren para hacer predicciones sobre un pasajero a partir del conjunto de evaluación. Los modelos 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 todo el conjunto de evaluación.

 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.
WARNING:tensorflow:Layer linear/linear_model is casting an input tensor from dtype float64 to the layer's dtype of float32, which is new behavior in TensorFlow 2.  The layer has dtype float32 because its dtype defaults to floatx.

If you intended to run this layer in float32, you can safely ignore this warning. If in doubt, this warning is likely only an issue if you are porting a TensorFlow 1.X model to TensorFlow 2.

To change all layers to have dtype float64 by default, call `tf.keras.backend.set_floatx('float64')`. To change just this layer, pass dtype='float64' to the layer constructor. If you are the author of this layer, you can disable autocasting by passing autocast=False to the base Layer constructor.

INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from /tmp/tmp0eiksj9v/model.ckpt-200
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.

<matplotlib.axes._subplots.AxesSubplot at 0x7fd21254e128>

png

Finalmente, observe la característica operativa del receptor (ROC) de los resultados, lo que nos dará una mejor idea de la compensación entre la tasa positiva verdadera y la tasa falsa positiva.

 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