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

Construye un modelo lineal con estimadores

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

Visión general

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

Preparar

!pip install -q sklearn

WARNING: You are using pip version 20.2.2; however, version 20.2.3 is available.
You should consider upgrading via the '/tmpfs/src/tf_docs_env/bin/python -m pip install --upgrade pip' command.

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

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 0x7f8e946914a8>

png

Hay aproximadamente el doble de pasajeros hombres que mujeres a bordo.

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

png

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

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

png

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

png

Ingeniería de características para el modelo

Los estimadores utilizan 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 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 eficaz. Una columna de características puede ser una de las entradas sin procesar en el dict características originales (una columna de características base ) o cualquier columna nueva creada usando transformaciones definidas en una o varias columnas base ( columnas de características 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 que se utilizan para el modelado. Además, proporcionan algunas capacidades de ingeniería de funciones como codificación en caliente, normalización y agrupación en cubos.

Columnas de entidades 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))

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

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

También puede inspeccionar el resultado de una columna de características específicas 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([[27.],
       [28.],
       [30.],
       [18.],
       [32.],
       [26.],
       [61.],
       [37.],
       [28.],
       [40.]], dtype=float32)

DenseFeatures solo acepta tensores densos, para inspeccionar una columna categórica, primero debe transformarla en una columna de indicador:

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.],
       [1., 0.],
       [1., 0.],
       [0., 1.],
       [1., 0.],
       [1., 0.],
       [1., 0.],
       [1., 0.],
       [1., 0.],
       [1., 0.]], dtype=float32)

Después de agregar todas las características base 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.7613636, 'accuracy_baseline': 0.625, 'auc': 0.809244, 'auc_precision_recall': 0.75609726, 'average_loss': 0.5452906, 'label/mean': 0.375, 'loss': 0.5347039, 'precision': 0.75, 'prediction/mean': 0.27201703, 'recall': 0.54545456, 'global_step': 200}

Columnas de entidades derivadas

Ahora alcanzó una precisión del 75%. El uso de cada columna de función 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 (p. Ej., Distinguiendo 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.7613636, 'accuracy_baseline': 0.625, 'auc': 0.84352624, 'auc_precision_recall': 0.78346276, 'average_loss': 0.48114488, 'label/mean': 0.375, 'loss': 0.4756022, 'precision': 0.65789473, 'prediction/mean': 0.4285249, 'recall': 0.75757575, 'global_step': 200}

Ahora logra una precisión del 77,6%, que es un poco 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 realizar 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/tmpg17o3o7e/model.ckpt-200
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.

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

png

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)

png