¡Reserva! Google I / O regresa del 18 al 20 de mayo Regístrese ahora
Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Construya 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.

Configuración

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 del Titanic con el objetivo (bastante morboso) de predecir la supervivencia de los pasajeros, dadas características como género, edad, 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)
<AxesSubplot:>

png

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

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

png

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

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

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 usan para el modelado. Además, brindan algunas capacidades de ingeniería de características 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 se convierten los datos en untf.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'Second' b'Third' b'Third' b'Third'
 b'Third' b'Third']

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

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()
array([[28.],
       [37.],
       [28.],
       [29.],
       [23.],
       [39.],
       [28.],
       [20.],
       [25.],
       [29.]], 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()
array([[1., 0.],
       [1., 0.],
       [1., 0.],
       [0., 1.],
       [0., 1.],
       [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. Entrenar 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.75, 'accuracy_baseline': 0.625, 'auc': 0.8341292, 'auc_precision_recall': 0.7951914, 'average_loss': 0.47351855, 'label/mean': 0.375, 'loss': 0.4655793, 'precision': 0.6666667, 'prediction/mean': 0.39508897, 'recall': 0.6666667, 'global_step': 200}

Columnas de entidades derivadas

Ahora alcanzó 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 un sexo 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 dividir 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.84239364, 'auc_precision_recall': 0.79337347, 'average_loss': 0.48490247, 'label/mean': 0.375, 'loss': 0.4779845, 'precision': 0.6454545, 'prediction/mean': 0.44535, 'recall': 0.7171717, 'global_step': 200}

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

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