Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/tutorials/structured_data/feature_columns.ipynb
25118 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

Clasificar datos estructurados con columnas de características

Advertencia: El módulo tf.feature_columns descrito en este tutorial no se recomienda para código nuevo. Las capas de preprocesamiento Keras cubren esta funcionalidad, para instrucciones de migración consulte la guía Migrando columnas de características. El módulo tf.feature_columns fue diseñado para usarse con los Estimators de TF1. Entra dentro de nuestras garantías de compatibilidad, pero no recibirá más correcciones que las vulnerabilidades de seguridad.

Este tutorial muestra cómo clasificar datos estructurados (por ejemplo, datos tabulares en un CSV). Usaremos Keras para definir el modelo, y tf.feature_column como puente para mapear desde columnas en un CSV a características usadas para entrenar el modelo. Este tutorial contiene el código completo para:

  • Cargar un archivo CSV usando Pandas.

  • Construir una canalización de entrada para procesar por lotes y mezclar las filas usando tf.data.

  • Mapear de columnas en el CSV a características usadas para entrenar el modelo usando columnas de características.

  • Construir, entrenar y evaluar un modelo usando Keras.

El conjunto de datos

Usaremos una versión simplificada del conjunto de datos de PetFinder. Hay varios miles de filas en el CSV. Cada fila describe una mascota y cada columna describe un atributo. Usaremos esta información para predecir la velocidad a la que se adoptará la mascota.

A continuación se describe este conjunto de datos. Observe que hay columnas numéricas y categóricas. Hay una columna de texto libre que no usaremos en este tutorial.

ColumnaDescripciónTipo de característicaTipo de datos
TypeTipo de animal (Dog, Cat)Categóricacadena
AgeEdad de la mascotaNuméricoentero
Breed1Raza principal de la mascotaCategóricacadena
Color1Color 1 de la mascotaCategóricacadena
Color2Color 2 de la mascotaCategóricacadena
MaturitySizeTamaño de adultoCategóricacadena
FurLengthLargo de peloCategóricacadena
VaccinatedLa mascota ha sido vacunadaCategóricacadena
SterilizedLa mascota ha sido esterilizadaCategóricacadena
HealthCondición de saludCategóricacadena
FeeTarifa de adopciónNuméricaentero
DescriptionReseña del perfil de esta mascotaTextocadena
PhotoAmtTotal de fotos subidas para esta mascotaNuméricaentero
AdoptionSpeedRapidez de adopciónClasificaciónentero

Importar TensorFlow y otras librerías

!pip install sklearn
import numpy as np import pandas as pd import tensorflow as tf from tensorflow import feature_column from tensorflow.keras import layers from sklearn.model_selection import train_test_split

Usar Pandas para crear un dataframe

Pandas es una librería de Python con muchas utilidades útiles para cargar y trabajar con datos estructurados. Usaremos Pandas para descargar el conjunto de datos desde una URL, y cargarlo en un dataframe.

import pathlib dataset_url = 'http://storage.googleapis.com/download.tensorflow.org/data/petfinder-mini.zip' csv_file = 'datasets/petfinder-mini/petfinder-mini.csv' tf.keras.utils.get_file('petfinder_mini.zip', dataset_url, extract=True, cache_dir='.') dataframe = pd.read_csv(csv_file)
dataframe.head()

Crear variable objetivo

La tarea en el conjunto de datos original es predecir la velocidad a la que se adoptará una mascota (por ejemplo, en la primera semana, el primer mes, los tres primeros meses, etc.). Simplifiquemos esto para nuestro tutorial. Aquí, transformaremos esto en un problema de clasificación binaria, y simplemente predeciremos si la mascota fue adoptada, o no.

Tras modificar la columna de la etiqueta, 0 indicará que la mascota no fue adoptada y 1 que sí lo fue.

# In the original dataset "4" indicates the pet was not adopted. dataframe['target'] = np.where(dataframe['AdoptionSpeed']==4, 0, 1) # Drop un-used columns. dataframe = dataframe.drop(columns=['AdoptionSpeed', 'Description'])

Dividir el dataframe en entrenamiento, validación y prueba

El conjunto de datos que descargamos era un único archivo CSV. Lo dividiremos en conjuntos de entrenamiento, validación y prueba.

train, test = train_test_split(dataframe, test_size=0.2) train, val = train_test_split(train, test_size=0.2) print(len(train), 'train examples') print(len(val), 'validation examples') print(len(test), 'test examples')

Crear una canalización de entrada usando tf.data

A continuación, encapsularemos los marcos de datos con tf.data. Esto nos permitirá usar columnas de características como puente para mapear desde las columnas del dataframe de Pandas a las características usadas para entrenar el modelo. Si estuviéramos trabajando con un archivo CSV muy grande (tan grande que no cupiera en memoria), usaríamos tf.data para leerlo directamente del disco. Eso no se trata en este tutorial.

# A utility method to create a tf.data dataset from a Pandas Dataframe def df_to_dataset(dataframe, shuffle=True, batch_size=32): dataframe = dataframe.copy() labels = dataframe.pop('target') ds = tf.data.Dataset.from_tensor_slices((dict(dataframe), labels)) if shuffle: ds = ds.shuffle(buffer_size=len(dataframe)) ds = ds.batch(batch_size) return ds
batch_size = 5 # A small batch sized is used for demonstration purposes train_ds = df_to_dataset(train, batch_size=batch_size) val_ds = df_to_dataset(val, shuffle=False, batch_size=batch_size) test_ds = df_to_dataset(test, shuffle=False, batch_size=batch_size)

Comprender la canalización de entrada

Ahora que hemos creado la canalización de entrada, vamos a llamarla para ver el formato de los datos que devuelve. Hemos usado un tamaño de lote pequeño para mantener la salida legible.

for feature_batch, label_batch in train_ds.take(1): print('Every feature:', list(feature_batch.keys())) print('A batch of ages:', feature_batch['Age']) print('A batch of targets:', label_batch )

Podemos ver que el conjunto de datos devuelve un diccionario de nombres de columnas (del dataframe) que mapean con valores de columnas de filas del dataframe.

Demostrar varios tipos de columnas de características

TensorFlow proporciona muchos tipos de columnas de características. En esta sección, crearemos varios tipos de columnas de características y demostraremos cómo transforman una columna del dataframe.

# We will use this batch to demonstrate several types of feature columns example_batch = next(iter(train_ds))[0]
# A utility method to create a feature column # and to transform a batch of data def demo(feature_column): feature_layer = layers.DenseFeatures(feature_column) print(feature_layer(example_batch).numpy())

Columnas numéricas

La salida de una columna de características se convierte en la entrada del modelo (usando la función demo definida anteriormente, podremos ver exactamente cómo se transforma cada columna del dataframe). Una columna numérica es el tipo más simple de columna. Se usa para representar características de valor real. Al usar esta columna, su modelo recibirá el valor de la columna del dataframe sin cambios.

photo_count = feature_column.numeric_column('PhotoAmt') demo(photo_count)

En el conjunto de datos PetFinder, la mayoría de las columnas del dataframe son categóricas.

Columnas por cubos

A menudo, no querrá introducir un número directamente en el modelo, sino dividir su valor en diferentes categorías basadas en rangos numéricos. Consideremos los datos brutos que representan la edad de una persona. En lugar de representar la edad como una columna numérica, podríamos dividir la edad en varios cubos usando una columna por cubos. Observe que los valores de un punto que aparecen a continuación describen a qué rango de edad corresponde cada fila.

age = feature_column.numeric_column('Age') age_buckets = feature_column.bucketized_column(age, boundaries=[1, 3, 5]) demo(age_buckets)

Columnas categóricas

En este conjunto de datos, el tipo se representa como una cadena (por ejemplo, 'Dog', o 'Cat'). No podemos introducir cadenas directamente en un modelo. En su lugar, primero debemos mapearlas a valores numéricos. Las columnas del vocabulario categórico proporcionan una forma de representar las cadenas como un vector de un solo punto (muy parecido a lo que ha visto anteriormente con los cubos de edad). El vocabulario puede pasarse como una lista usando categorical_column_with_vocabulary_list, o cargarse desde un archivo usando categorical_column_with_vocabulary_file.

animal_type = feature_column.categorical_column_with_vocabulary_list( 'Type', ['Cat', 'Dog']) animal_type_one_hot = feature_column.indicator_column(animal_type) demo(animal_type_one_hot)

Incorporación de columnas

Supongamos que en lugar de tener sólo unas pocas cadenas posibles, tenemos miles (o más) de valores por categoría. Por diversos motivos, a medida que el número de categorías progresa, resulta inviable entrenar una red neuronal usando codificaciones de un solo paso. Podemos usar una columna de incorporación para superar esta limitación. En lugar de representar los datos como un vector unívoco de muchas dimensiones, una columna de incorporación representa esos datos como un vector denso de dimensiones inferiores en el que cada celda puede contener cualquier número, no sólo 0 o 1. El tamaño de la incorporación (8, en el ejemplo siguiente) es un parámetro que debe ajustarse.

Punto clave: usar una columna de incorporación es lo mejor cuando una columna categórica tiene muchos valores posibles. Aquí estamos usando una con fines de demostración, para que tenga un ejemplo completo que pueda modificar para un conjunto de datos diferente en el futuro.

# Notice the input to the embedding column is the categorical column # we previously created breed1 = feature_column.categorical_column_with_vocabulary_list( 'Breed1', dataframe.Breed1.unique()) breed1_embedding = feature_column.embedding_column(breed1, dimension=8) demo(breed1_embedding)

Columnas de características hasheadas

Otra forma de representar una columna categórica con un gran número de valores es usar una categorical_column_with_hash_bucket. Esta columna categórica calcula un valor hash de la entrada y, a continuación, selecciona uno de los cubos hash_bucket_size para codificar una cadena. Al usar esta columna, no necesita proporcionar el vocabulario, y puede seleccionar que el número de hash_buckets sea significativamente menor que el número de categorías reales para ahorrar espacio.

Punto clave: Un inconveniente importante de esta técnica es que puede haber colisiones en las que se mapeen cadenas diferentes en el mismo cubo. En la práctica, esto puede funcionar bien para algunos conjuntos de datos a pesar de todo.

breed1_hashed = feature_column.categorical_column_with_hash_bucket( 'Breed1', hash_bucket_size=10) demo(feature_column.indicator_column(breed1_hashed))

Columnas de características cruzadas

La combinación de características en una única característica, más conocida como cruces de características, permite a un modelo aprender ponderaciones separadas para cada combinación de características. Aquí, crearemos una nueva característica que es el cruce de Edad y Tipo. Tenga en cuenta que crossed_column no construye la tabla completa de todas las combinaciones posibles (que podría ser muy grande). En su lugar, está respaldada por una hashed_column, de modo que puede seleccionar el tamaño de la tabla.

crossed_feature = feature_column.crossed_column([age_buckets, animal_type], hash_bucket_size=10) demo(feature_column.indicator_column(crossed_feature))

Seleccionar qué columnas usar

Hemos visto cómo usar varios tipos de columnas de características. Ahora las usaremos para entrenar un modelo. La meta de este tutorial es mostrarle el código completo (por ejemplo, la mecánica) necesario para trabajar con columnas de características. A continuación, hemos seleccionado arbitrariamente algunas columnas para entrenar nuestro modelo.

Punto clave: Si su objetivo es construir un modelo preciso, pruebe con un conjunto de datos propio más amplio y piense detenidamente qué características son las más significativas que debe incluir y cómo deben representarse.

feature_columns = [] # numeric cols for header in ['PhotoAmt', 'Fee', 'Age']: feature_columns.append(feature_column.numeric_column(header))
# bucketized cols age = feature_column.numeric_column('Age') age_buckets = feature_column.bucketized_column(age, boundaries=[1, 2, 3, 4, 5]) feature_columns.append(age_buckets)
# indicator_columns indicator_column_names = ['Type', 'Color1', 'Color2', 'Gender', 'MaturitySize', 'FurLength', 'Vaccinated', 'Sterilized', 'Health'] for col_name in indicator_column_names: categorical_column = feature_column.categorical_column_with_vocabulary_list( col_name, dataframe[col_name].unique()) indicator_column = feature_column.indicator_column(categorical_column) feature_columns.append(indicator_column)
# embedding columns breed1 = feature_column.categorical_column_with_vocabulary_list( 'Breed1', dataframe.Breed1.unique()) breed1_embedding = feature_column.embedding_column(breed1, dimension=8) feature_columns.append(breed1_embedding)
# crossed columns age_type_feature = feature_column.crossed_column([age_buckets, animal_type], hash_bucket_size=100) feature_columns.append(feature_column.indicator_column(age_type_feature))

Crear una capa de características

Ahora que hemos definido nuestras columnas de características, usaremos una capa DenseFeatures para introducirlas en nuestro modelo Keras.

feature_layer = tf.keras.layers.DenseFeatures(feature_columns)

Anteriormente, usamos un tamaño de lote pequeño para demostrar cómo funcionaban las columnas de características. Creamos una nueva canalización de entrada con un tamaño de lote mayor.

batch_size = 32 train_ds = df_to_dataset(train, batch_size=batch_size) val_ds = df_to_dataset(val, shuffle=False, batch_size=batch_size) test_ds = df_to_dataset(test, shuffle=False, batch_size=batch_size)

Crear, compilar y entrenar el modelo

model = tf.keras.Sequential([ feature_layer, layers.Dense(128, activation='relu'), layers.Dense(128, activation='relu'), layers.Dropout(.1), layers.Dense(1) ]) model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy']) model.fit(train_ds, validation_data=val_ds, epochs=10)
loss, accuracy = model.evaluate(test_ds) print("Accuracy", accuracy)

Punto clave: Normalmente obtendrá mejores resultados con el aprendizaje profundo con conjuntos de datos mucho más grandes y complejos. Cuando trabaje con un conjunto de datos pequeño como éste, le recomendamos usar un árbol de decisión o un bosque aleatorio como línea de referencia sólida. La meta de este tutorial no es entrenar un modelo preciso, sino demostrar la mecánica de trabajo con datos estructurados, para que disponga de código que pueda usar como punto de partida cuando trabaje con sus propios conjuntos de datos en el futuro.

Siguientes pasos

La mejor manera de aprender más sobre la clasificación de datos estructurados es intentarlo usted mismo. Le sugerimos que encuentre otro conjunto de datos con el que trabajar y entrene un modelo para clasificarlo utilizando un código similar al anterior. Para mejorar la precisión, piense detenidamente qué características incluir en su modelo y cómo deben representarse.