Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/tutorials/structured_data/preprocessing_layers.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 usando capas de preprocesamiento Keras

Este tutorial muestra cómo clasificar datos estructurados, como datos tabulares, usando una versión simplificada del conjunto de datos PetFinder de un concurso de Kaggle almacenado en un archivo CSV.

Utilizará Keras para definir el modelo, y capas de preprocesamiento Keras como puente para mapear desde columnas en un archivo CSV a características utilizadas para entrenar el modelo. La meta es predecir si una mascota será adoptada.

Este tutorial contiene el código completo para:

  • Carga de un archivo CSV en un DataFrame usando pandas.

  • Construir una canalización de entrada para procesar por lotes y barajar las filas usando tf.data (visite tf.data: Construir canalizaciones de entrada TensorFlow para más detalles).

  • Mapeo de las columnas del archivo CSV a las características usadas para entrenar el modelo con las capas de preprocesamiento de Keras.

  • Construir, entrenar y evaluar un modelo usando los métodos incorporados de Keras.

Nota: Este tutorial es similar a Clasificar datos estructurados con columnas de características. Esta versión usa las capas de preprocesamiento Keras en lugar de la API tf.feature_column, ya que las primeras son más intuitivas y pueden incluirse fácilmente dentro de su modelo para simplificar la implementación.

El mini conjunto de datos PetFinder.my

Hay varios miles de filas en el mini archivo de datos CSV de PetFinder.my, donde cada fila describe una mascota (un perro o un gato) y cada columna describe un atributo, como la edad, la raza, el color, etc.

En el resumen del conjunto de datos que aparece a continuación, observe que hay principalmente columnas numéricas y categóricas. En este tutorial, sólo se ocupará de esos dos tipos de características, eliminando Description (una característica de texto libre) y AdoptionSpeed (una característica de clasificación) durante el preprocesamiento de los datos.

ColumnaDescripción de mascotaTipo de característicaTipo de datos
TypeTipo de animal (Dog, Cat)Categóricacadena
AgeEdadNuméricaentero
Breed1Raza primariaCategóricacadena
Color1Color 1Categóricacadena
Color2Color 2Categó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
DescriptionRedacción del perfilTextocadena
PhotoAmtTotal de fotos subidasNuméricaentero
AdoptionSpeedRapidez de adopción categóricaClasificaciónentero

Importar TensorFlow y otras librerías

import numpy as np import pandas as pd import tensorflow as tf from tensorflow.keras import layers
tf.__version__

Cargar el conjunto de datos y leerlo en un DataFrame pandas

pandas es una librería de Python con muchas utilidades útiles para cargar y trabajar con datos estructurados. Use tf.keras.utils.get_file para descargar y extraer el archivo CSV con el miniconjunto de datos PetFinder.my, y cárguelo en un DataFrame con pandas.read_csv:

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)

Inspeccione el conjunto de datos comprobando las cinco primeras filas del DataFrame:

dataframe.head()

Crear una variable objetivo

La tarea original del concurso de Kaggle sobre predicción de adopciones PetFinder.my consistía en predecir la velocidad a la que se adoptará una mascota (por ejemplo, en la primera semana, el primer mes, los tres primeros meses, etc.).

En este tutorial, simplificará la tarea transformándola en un problema de clasificación binaria, en el que simplemente tendrá que predecir si una mascota ha sido adoptada o no.

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

# In the original dataset, `'AdoptionSpeed'` of `4` indicates # a pet was not adopted. dataframe['target'] = np.where(dataframe['AdoptionSpeed']==4, 0, 1) # Drop unused features. dataframe = dataframe.drop(columns=['AdoptionSpeed', 'Description'])

Dividir el DataFrame en conjuntos de entrenamiento, validación y prueba

El conjunto de datos está en un único DataFrame pandas. Divídalo en conjuntos de entrenamiento, validación y prueba usando, por ejemplo, una proporción 80:10:10, respectivamente:

train, val, test = np.split(dataframe.sample(frac=1), [int(0.8*len(dataframe)), int(0.9*len(dataframe))])
print(len(train), 'training examples') print(len(val), 'validation examples') print(len(test), 'test examples')

Crear una canalización de entrada usando tf.data

A continuación, cree una función de utilidad que convierta cada conjunto de datos de entrenamiento, validación y prueba en un tf.data.Dataset y, a continuación, mezcle y agrupe los datos.

Nota: Si estuviera trabajando con un archivo CSV muy grande (tan grande que no cupiera en memoria), usaría la API tf.data para leerlo directamente del disco. Eso no se trata en este tutorial.

def df_to_dataset(dataframe, shuffle=True, batch_size=32): df = dataframe.copy() labels = df.pop('target') df = {key: value[:,tf.newaxis] for key, value in dataframe.items()} ds = tf.data.Dataset.from_tensor_slices((dict(df), labels)) if shuffle: ds = ds.shuffle(buffer_size=len(dataframe)) ds = ds.batch(batch_size) ds = ds.prefetch(batch_size) return ds

Ahora, use la función recién creada (df_to_dataset) para comprobar el formato de los datos que devuelve la función ayudante a la canalización de entrada llamándola sobre los datos de entrenamiento, y use un tamaño de lote pequeño para mantener la legibilidad de la salida:

batch_size = 5 train_ds = df_to_dataset(train, batch_size=batch_size)
[(train_features, label_batch)] = train_ds.take(1) print('Every feature:', list(train_features.keys())) print('A batch of ages:', train_features['Age']) print('A batch of targets:', label_batch )

Como demuestra la salida, el conjunto de entrenamiento devuelve un diccionario de nombres de columnas (del DataFrame) que se mapean a valores de columnas de filas.

Aplicar las capas de preprocesamiento Keras

Las capas de preprocesamiento de Keras le permiten construir canalizaciones de procesamiento de entrada nativas de Keras, que pueden usarse como código de preprocesamiento independiente en flujos de trabajo no Keras, combinarse directamente con modelos Keras y exportarse como parte de un SavedModel de Keras.

En este tutorial, usará las cuatro capas de preprocesamiento siguientes para demostrar cómo realizar el preprocesamiento, la codificación de datos estructurados y la ingeniería de características:

  • tf.keras.layers.Normalization: Realiza la normalización de las características de entrada.

  • tf.keras.layers.CategoryEncoding: Convierte los rasgos categóricos enteros en representaciones densas de uno, varios o tf-idf pasos.

  • tf.keras.layers.StringLookup: Convierte los valores categóricos de cadena en índices enteros.

  • tf.keras.layers.IntegerLookup: Convierte valores categóricos enteros en índices enteros.

Puede obtener más información sobre las capas disponibles en la guía Trabajar con capas de preprocesamiento.

  • Para las características numéricas del miniconjunto de datos PetFinder.my, usará una capa tf.keras.layers.Normalization para normalizar la distribución de los datos.

  • Para las características categóricas, como las Type de mascotas (Dog y Cat), las transformará en tensores codificados con tf.keras.layers.CategoryEncoding.

Columnas numéricas

Para cada característica numérica del miniconjunto de datos PetFinder.my, usará una capa tf.keras.layers.Normalization para estandarizar la distribución de los datos.

Defina una nueva función de utilidad que devuelva una capa que aplique la normalización por características a las características numéricas usando esa capa Keras de preprocesamiento:

def get_normalization_layer(name, dataset): # Create a Normalization layer for the feature. normalizer = layers.Normalization(axis=None) # Prepare a Dataset that only yields the feature. feature_ds = dataset.map(lambda x, y: x[name]) # Learn the statistics of the data. normalizer.adapt(feature_ds) return normalizer

A continuación, pruebe la nueva función llamándola sobre el total de características de las fotos de mascotas cargadas para normalizar 'PhotoAmt':

photo_count_col = train_features['PhotoAmt'] layer = get_normalization_layer('PhotoAmt', train_ds) layer(photo_count_col)

Nota: Si tiene muchas características numéricas (cientos, o más), es más eficiente concatenarlas primero y usar una única capa tf.keras.layers.Normalization.

Columnas categóricas

El Tipo de mascota en el conjunto de datos se representa como cadenas-Perroy Gato-que deben codificarse de forma múltiple antes de introducirse en el modelo. La característica Age

Defina otra nueva función de utilidad que devuelva una capa que mapee valores de un vocabulario a índices enteros y codifique de forma múltiple las características usando las capas de preprocesamiento tf.keras.layers.StringLookup, tf.keras.layers.IntegerLookup, y tf.keras.CategoryEncoding:

def get_category_encoding_layer(name, dataset, dtype, max_tokens=None): # Create a layer that turns strings into integer indices. if dtype == 'string': index = layers.StringLookup(max_tokens=max_tokens) # Otherwise, create a layer that turns integer values into integer indices. else: index = layers.IntegerLookup(max_tokens=max_tokens) # Prepare a `tf.data.Dataset` that only yields the feature. feature_ds = dataset.map(lambda x, y: x[name]) # Learn the set of possible values and assign them a fixed integer index. index.adapt(feature_ds) # Encode the integer indices. encoder = layers.CategoryEncoding(num_tokens=index.vocabulary_size()) # Apply multi-hot encoding to the indices. The lambda function captures the # layer, so you can use them, or include them in the Keras Functional model later. return lambda feature: encoder(index(feature))

Pruebe la función get_category_encoding_layer llamándola sobre rasgos 'Type' de mascota para convertirlos en tensores codificados multihilo:

test_type_col = train_features['Type'] test_type_layer = get_category_encoding_layer(name='Type', dataset=train_ds, dtype='string') test_type_layer(test_type_col)

Repita el proceso en las características 'Age' de la mascota:

test_age_col = train_features['Age'] test_age_layer = get_category_encoding_layer(name='Age', dataset=train_ds, dtype='int64', max_tokens=5) test_age_layer(test_age_col)

Preprocesar las características seleccionadas para entrenar sobre el modelo

Ha aprendido a usar varios tipos de capas de preprocesamiento Keras. A continuación, hará lo siguiente:

  • Aplicará las funciones de utilidad de preprocesamiento definidas anteriormente a 13 características numéricas y categóricas del miniconjunto de datos PetFinder.my.

  • Añada todas las entradas de características a una lista.

Como se mencionó al principio, para entrenar el modelo, usará las características numéricas ('PhotoAmt', 'Fee') y categóricas ('Age', 'Type', 'Color1', 'Color2', 'Sex', 'MaturitySize', 'FurLength', 'Vaccinated', 'Sterilized', 'Health', 'Breed1') del miniconjunto de datos PetFinder.my.

Nota: 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.

Anteriormente, usó un tamaño de lote pequeño para demostrar la canalización de entrada. Ahora creemos una nueva canalización de entrada con un tamaño de lote mayor, de 256:

batch_size = 256 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)

Normalice las características numéricas (el número de fotos de mascotas y la cuota de adopción) y añádalas a una lista de entradas llamada encoded_features:

all_inputs = [] encoded_features = [] # Numerical features. for header in ['PhotoAmt', 'Fee']: numeric_col = tf.keras.Input(shape=(1,), name=header) normalization_layer = get_normalization_layer(header, train_ds) encoded_numeric_col = normalization_layer(numeric_col) all_inputs.append(numeric_col) encoded_features.append(encoded_numeric_col)

Convierta los valores categóricos enteros del conjunto de datos (la edad de la mascota) en índices enteros, realice una codificación de múltiples pasos y añada las entradas de características resultantes a encoded_features:

age_col = tf.keras.Input(shape=(1,), name='Age', dtype='int64') encoding_layer = get_category_encoding_layer(name='Age', dataset=train_ds, dtype='int64', max_tokens=5) encoded_age_col = encoding_layer(age_col) all_inputs.append(age_col) encoded_features.append(encoded_age_col)

Repita el mismo paso para los valores categóricos de cadena:

categorical_cols = ['Type', 'Color1', 'Color2', 'Gender', 'MaturitySize', 'FurLength', 'Vaccinated', 'Sterilized', 'Health', 'Breed1'] for header in categorical_cols: categorical_col = tf.keras.Input(shape=(1,), name=header, dtype='string') encoding_layer = get_category_encoding_layer(name=header, dataset=train_ds, dtype='string', max_tokens=5) encoded_categorical_col = encoding_layer(categorical_col) all_inputs.append(categorical_col) encoded_features.append(encoded_categorical_col)

Crear, compilar y entrenar el modelo

El siguiente paso es crear un modelo usando la API Functional de Keras. Para la primera capa de su modelo, fusione la lista de entradas de características (encoded_features) en un vector mediante concatenación con tf.keras.layers.concatenate.

all_features = tf.keras.layers.concatenate(encoded_features) x = tf.keras.layers.Dense(32, activation="relu")(all_features) x = tf.keras.layers.Dropout(0.5)(x) output = tf.keras.layers.Dense(1)(x) model = tf.keras.Model(all_inputs, output)

Configure el modelo con Model.compile de Keras:

model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=["accuracy"])

Visualicemos el grafo de conectividad:

# Use `rankdir='LR'` to make the graph horizontal. tf.keras.utils.plot_model(model, show_shapes=True, rankdir="LR")

A continuación, entrene el modelo:

model.fit(train_ds, epochs=10, validation_data=val_ds)
loss, accuracy = model.evaluate(test_ds) print("Accuracy", accuracy)

Realizar inferencias

El modelo que ha desarrollado ahora puede clasificar una fila a partir de un archivo CSV directamente después de haber incluido las capas de preprocesamiento dentro del propio modelo.

Ahora puede guardar y volver a cargar el modelo Keras con Model.save y Model.load_model antes de realizar la inferencia sobre nuevos datos:

model.save('my_pet_classifier.keras') reloaded_model = tf.keras.models.load_model('my_pet_classifier.keras')

Para obtener una predicción para una nueva muestra, basta con llamar al método Model.predict de Keras. Sólo tiene que hacer dos cosas:

  1. Encapsule los escalares en una lista para que tengan una dimensión de lote (Models sólo procesan lotes de datos, no muestras individuales).

  2. Llame a tf.convert_to_tensor sobre cada característica.

sample = { 'Type': 'Cat', 'Age': 3, 'Breed1': 'Tabby', 'Gender': 'Male', 'Color1': 'Black', 'Color2': 'White', 'MaturitySize': 'Small', 'FurLength': 'Short', 'Vaccinated': 'No', 'Sterilized': 'No', 'Health': 'Healthy', 'Fee': 100, 'PhotoAmt': 2, } input_dict = {name: tf.convert_to_tensor([value]) for name, value in sample.items()} predictions = reloaded_model.predict(input_dict) prob = tf.nn.sigmoid(predictions[0]) print( "This particular pet had a %.1f percent probability " "of getting adopted." % (100 * prob) )

Nota: Normalmente obtendrá mejores resultados con el aprendizaje profundo con conjuntos de datos más grandes y complejos. Cuando trabaje con un conjunto de datos pequeño, como el simplificado PetFinder.my, puede usar un árbol de decisión o un bosque aleatorio como línea de referencia sólida. La meta de este tutorial es demostrar la mecánica de trabajar con datos estructurados, para que tenga un punto de partida cuando trabaje con sus propios conjuntos de datos en el futuro.

Siguientes pasos

Para aprender más sobre la clasificación de datos estructurados, pruebe a trabajar con otros conjuntos de datos. Para mejorar la precisión durante el entrenamiento y las pruebas de sus modelos, piense detenidamente qué características incluir en su modelo y cómo deben representarse.

Aquí tiene algunas sugerencias de conjuntos de datos: