Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/tutorials/load_data/pandas_dataframe.ipynb
25118 views
Kernel: Python 3

Licensed under the Apache License, Version 2.0 (the "License");

#@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.

Cargar un DataFrame de Pandas

En este tutorial encontrará ejemplos de cómo cargar DataFrames de Pandas en TensorFlow.

Utilizará un conjunto de datos de enfermedades cardiovasculares reducido que se obtuvo del repositorio de datos de aprendizaje automático de la Universidad de California (UCI). Hay cientos de filas en el archivo CSV. En cada fila se describe un paciente y en cada columna se describe un atributo. Usará esta información para predecir si el paciente tiene una enfermedad cardiovascular o no, que es una tarea de clasificación binaria.

Lectura de datos con Panda

import pandas as pd import tensorflow as tf SHUFFLE_BUFFER = 500 BATCH_SIZE = 2

Descargue el archivo CSV que tiene el conjunto de datos de las enfermedades cardiovasculares:

csv_file = tf.keras.utils.get_file('heart.csv', 'https://storage.googleapis.com/download.tensorflow.org/data/heart.csv')

Lea el archivo CSV con Pandas:

df = pd.read_csv(csv_file)

Los datos se verán así:

df.head()
df.dtypes

Generará modelos para predecir la etiqueta que contiene la columna target.

target = df.pop('target')

Un DataFrame como un arreglo

Si sus datos tienen un tipo de datos uniforme o dtype, es posible usar un DataFrame de Pandas en donde sea que se pueda usar un arreglo de NumPy. Esto funciona porque la clase pandas.DataFrame admite el protocolo __array__ y la función tf.convert_to_tensor de TensorFlow acepta los objetos que admiten el protocolo.

Tome las características numéricas del conjunto de datos (omita las características categóricas por el momento):

numeric_feature_names = ['age', 'thalach', 'trestbps', 'chol', 'oldpeak'] numeric_features = df[numeric_feature_names] numeric_features.head()

El DataFrame puede convertirse en un arreglo de NumPy con la propiedad DataFrame.values o numpy.array(df). Para convertirlo en un tensor, use tf.convert_to_tensor:

tf.convert_to_tensor(numeric_features)

En general, si se puede convertir un objeto en tensor con tf.convert_to_tensor, también puede pasarse donde sea que se pueda pasar un tf.Tensor.

Con Model.fit

Un DataFrame, que se interprete con un tensor individual, puede usarse directamente como un argumento para el método Model.fit.

A continuación, encontrará un ejemplo de cómo entrenar un modelo con las características numéricas de un conjunto de datos.

El primer paso es normalizar los rangos de entrada. Para hacerlo, use una capa tf.keras.layers.Normalization.

Para ver la media y la desviación estándar de la capa antes de ejecutarla, asegúrese de llamar al método Normalization.adapt:

normalizer = tf.keras.layers.Normalization(axis=-1) normalizer.adapt(numeric_features)

Llame a la capa en las primeras tres filas del DataFrame para visualizar un ejemplo de la salida de esta capa:

normalizer(numeric_features.iloc[:3])

Use la capa de normalización como la primera capa de un modelo simple:

def get_basic_model(): model = tf.keras.Sequential([ normalizer, tf.keras.layers.Dense(10, activation='relu'), tf.keras.layers.Dense(10, activation='relu'), tf.keras.layers.Dense(1) ]) model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy']) return model

Cuando pasa el DataFrame como un argumento x a Model.fit, Keras trata al DataFrame como si fuera una matriz NumPy:

model = get_basic_model() model.fit(numeric_features, target, epochs=15, batch_size=BATCH_SIZE)

Con tf.data

Si quiere aplicar las transformaciones de tf.data al DataFrame de un dtype uniforme, el método Dataset.from_tensor_slices creará un conjunto de datos iterativo por las filas del DataFrame. Al inicio, cada fila es un vector de valores. Para entrenar un modelo, necesita parejas de (inputs, labels), entonces el paso de (features, labels) y Dataset.from_tensor_slices devolverá la pareja de segmentos necesaria:

numeric_dataset = tf.data.Dataset.from_tensor_slices((numeric_features, target)) for row in numeric_dataset.take(3): print(row)
numeric_batches = numeric_dataset.shuffle(1000).batch(BATCH_SIZE) model = get_basic_model() model.fit(numeric_batches, epochs=15)

DataFrame como un diccionario

Cuando empiece a tratar datos heterogéneos, ya no será posible tratar el DataFrame como si fuera un arreglo individual. Los tensores de TensorFlow requieren que todos los elementos tengan el mismo dtype.

Por lo tanto, en este caso, necesita empezar a tratarlo como un diccionario de columnas, donde cada columna tiene un dtype uniforme. Un DataFrame es muy parecido a un diccionario de arreglos, por eso, por lo general, lo único que debe hacer es convertir el DataFrame en un diccionario de Python. Muchas API importantes de TensorFlow admiten diccionarios (anidados) de arreglos como entradas.

La canalización de la entrada tf.data lo manipula muy bien. Todas las operaciones de tf.data manipulan diccionarios y tuplas automáticamente. Así que, para crear un conjunto de datos con ejemplos de diccionario de un DataFrame, solo conviértalo en un diccionario antes de segmentarlo con Dataset.from_tensor_slices:

numeric_dict_ds = tf.data.Dataset.from_tensor_slices((dict(numeric_features), target))

Estos son los primeros tres ejemplos del conjunto de datos:

for row in numeric_dict_ds.take(3): print(row)

Diccionarios con Keras

Generalmente, los modelos y las capas de Keras esperan tener un tensor de entrada individual, pero estas clases pueden aceptar y devolver estructuras anidadas de diccionarios, tuplas y tensores. Estas estructuras se conocen como "anidamientos" (vea el módulo de tf.nest para obtener más detalles).

Existen dos formas equivalentes para escribir un modelo de Keras que acepte un diccionario como entrada.

1. El estilo de modelo de subclase

Escribe una subclase de tf.keras.Model (o tf.keras.Layer) y manipula las entradas y crea las salidas de forma directa:

def stack_dict(inputs, fun=tf.stack): values = [] for key in sorted(inputs.keys()): values.append(tf.cast(inputs[key], tf.float32)) return fun(values, axis=-1)
#@title class MyModel(tf.keras.Model): def __init__(self): # Create all the internal layers in init. super().__init__(self) self.normalizer = tf.keras.layers.Normalization(axis=-1) self.seq = tf.keras.Sequential([ self.normalizer, tf.keras.layers.Dense(10, activation='relu'), tf.keras.layers.Dense(10, activation='relu'), tf.keras.layers.Dense(1) ]) def adapt(self, inputs): # Stack the inputs and `adapt` the normalization layer. inputs = stack_dict(inputs) self.normalizer.adapt(inputs) def call(self, inputs): # Stack the inputs inputs = stack_dict(inputs) # Run them through all the layers. result = self.seq(inputs) return result model = MyModel() model.adapt(dict(numeric_features)) model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy'], run_eagerly=True)

Este modelo puede aceptar un diccionario de columnas o un conjunto de datos de elementos del diccionario para el entrenamiento:

model.fit(dict(numeric_features), target, epochs=5, batch_size=BATCH_SIZE)
numeric_dict_batches = numeric_dict_ds.shuffle(SHUFFLE_BUFFER).batch(BATCH_SIZE) model.fit(numeric_dict_batches, epochs=5)

Estas son las predicciones para los primeros tres ejemplos:

model.predict(dict(numeric_features.iloc[:3]))

2. El estilo funcional de Keras

inputs = {} for name, column in numeric_features.items(): inputs[name] = tf.keras.Input( shape=(1,), name=name, dtype=tf.float32) inputs
x = stack_dict(inputs, fun=tf.concat) normalizer = tf.keras.layers.Normalization(axis=-1) normalizer.adapt(stack_dict(dict(numeric_features))) x = normalizer(x) x = tf.keras.layers.Dense(10, activation='relu')(x) x = tf.keras.layers.Dense(10, activation='relu')(x) x = tf.keras.layers.Dense(1)(x) model = tf.keras.Model(inputs, x) model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy'], run_eagerly=True)
tf.keras.utils.plot_model(model, rankdir="LR", show_shapes=True)

Puede entrenar el modelo funcional de la misma manera que un modelo de subclase:

model.fit(dict(numeric_features), target, epochs=5, batch_size=BATCH_SIZE)
numeric_dict_batches = numeric_dict_ds.shuffle(SHUFFLE_BUFFER).batch(BATCH_SIZE) model.fit(numeric_dict_batches, epochs=5)

Ejemplo completo

Si pasa un DataFrame heterogéneo a Keras, es posible que cada columna necesite un preprocesamiento único. Este preprocesamiento se puede hacer directamente en el DataFrame, pero para que el modelo funcione correctamente, las entradas deben preprocesarse de la misma forma. Por eso, el mejor enfoque es construir el preprocesamiento en el modelo. Las capas de preprocesamiento de Keras cubren muchas de las tareas comunes.

Construcción del encabezado de preprocesamiento

En este conjunto de datos de características "enteras" en los datos sin procesar son en realidad índices categóricos. Estos índices no están ordenados en valores numéricos (vea descripción del conjunto de datos para obtener más detalles). Como están desordenados son inadecuados para ser ingresados al modelo directamente; el modelo los interpretaría como si estuvieran en orden. Para usar estas entradas deberá codificarlas, como vectores de un paso o incorporación. Lo mismo aplica para las características categóricas de cadenas de texto.

Nota: Si tienen muchas características que necesitan un preprocesamiento idéntico, es más eficiente concatenarlos juntos antes de aplicar el preprocesamiento.

Por otro lado, las características binarias no necesitan codificarse ni normalizarse.

Para empezar, cree una lista de características de cada grupo:

binary_feature_names = ['sex', 'fbs', 'exang']
categorical_feature_names = ['cp', 'restecg', 'slope', 'thal', 'ca']

Luego, cree un modelo de preprocesamiento que aplicará el preprocesamiento adecuado a cada entrada y concatenará los resultados.

En esta sección se usa la API funcional de Keras para implementar el procesamiento. Primero debe crear un tf.keras.Input para cada columna del DataFrame:

inputs = {} for name, column in df.items(): if type(column[0]) == str: dtype = tf.string elif (name in categorical_feature_names or name in binary_feature_names): dtype = tf.int64 else: dtype = tf.float32 inputs[name] = tf.keras.Input(shape=(), name=name, dtype=dtype)
inputs

Para cada entrada, aplicará algunas transformaciones con las capas de Keras y las operaciones de TensorFlow. Cada característica empieza como un lote de escalares (shape=(batch,)). La salida de cada uno debería ser un lote de vectores tf.float32 (shape=(batch, n)). En el último paso, se concatenarán todos los vectores juntos.

Entradas binarias

Dado que las entradas binarias no necesitan ningún preprocesamiento, solo agregue el eje del vector, conviértalas en float32 y agréguelas a la lista de entradas preprocesadas:

preprocessed = [] for name in binary_feature_names: inp = inputs[name] inp = inp[:, tf.newaxis] float_value = tf.cast(inp, tf.float32) preprocessed.append(float_value) preprocessed

Entradas numéricas

Tal como ya hizo en la sección anterior, debe ejecutar estas entradas numéricas a través de una capa tf.keras.layers.Normalization antes de usarlas. La diferencia es que ahora las entradas son un diccionario. En el siguiente código, se recopilan las características numéricas del DataFrame, se apilan y se pasan al método Normalization.adapt.

normalizer = tf.keras.layers.Normalization(axis=-1) normalizer.adapt(stack_dict(dict(numeric_features)))

En el siguiente código, se apilan las características numéricas y se ejecutan a través de la capa de normalización.

numeric_inputs = {} for name in numeric_feature_names: numeric_inputs[name]=inputs[name] numeric_inputs = stack_dict(numeric_inputs) numeric_normalized = normalizer(numeric_inputs) preprocessed.append(numeric_normalized) preprocessed

Características categóricas

Para usar las características categóricas, primero debes codificarlas en vectores binarios o incorporaciones. Ya que estas características solo contienen pocas categorías, debe convertir las entradas en vectores de un paso directamente con la opción output_mode='one_hot', que admiten las capas tf.keras.layers.StringLookup y tf.keras.layers.IntegerLookup.

Aquí tiene un ejemplo de cómo funcionan estas capas:

vocab = ['a','b','c'] lookup = tf.keras.layers.StringLookup(vocabulary=vocab, output_mode='one_hot') lookup(['c','a','a','b','zzz'])
vocab = [1,4,7,99] lookup = tf.keras.layers.IntegerLookup(vocabulary=vocab, output_mode='one_hot') lookup([-1,4,1])

Para determinar el vocabulario de cada entrada, cree una capa para convertir el vocabulario en un vector de un paso:

for name in categorical_feature_names: vocab = sorted(set(df[name])) print(f'name: {name}') print(f'vocab: {vocab}\n') if type(vocab[0]) is str: lookup = tf.keras.layers.StringLookup(vocabulary=vocab, output_mode='one_hot') else: lookup = tf.keras.layers.IntegerLookup(vocabulary=vocab, output_mode='one_hot') x = inputs[name][:, tf.newaxis] x = lookup(x) preprocessed.append(x)

Ensamblar el encabezado de preprocesamiento

En este punto, preprocessed es solo una lista de Python de todos los resultados del preprocesamiento, cada resultado tiene la forma de (batch_size, depth):

preprocessed

Debe concatenar todas las características preprocesadas junto con el eje depth, así cada ejemplo del diccionario se convierte en un vector individual. El vector contiene características categóricas, características numéricas, y características categóricas de un solo paso:

preprocesssed_result = tf.concat(preprocessed, axis=-1) preprocesssed_result

Ahora, cree un modelo a partir de este cálculo para que se pueda reusar:

preprocessor = tf.keras.Model(inputs, preprocesssed_result)
tf.keras.utils.plot_model(preprocessor, rankdir="LR", show_shapes=True)

Para probar el preprocesador, use el descriptor de acceso DataFrame.iloc para segmentar el primer ejemplo extraído del DataFrame. Luego, conviértalo en un diccionario y pase el diccionario al preprocesador. El resultado es un vector individual que contiene características binarias, características numéricas normalizadas y características categóricas de un solo paso, en ese orden:

preprocessor(dict(df.iloc[:1]))

Crear y entrenar un modelo

Ahora, desarrolle la parte principal del modelo. Use la configuración del ejemplo anterior. Un par de capas lineales rectificadas Dense y una capa externa Dense(1) para la clasificación.

body = tf.keras.Sequential([ tf.keras.layers.Dense(10, activation='relu'), tf.keras.layers.Dense(10, activation='relu'), tf.keras.layers.Dense(1) ])

Ahora puede unir las dos partes con el API funcional de Keras.

inputs
x = preprocessor(inputs) x
result = body(x) result
model = tf.keras.Model(inputs, result) model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy'])

Este modelo espera un diccionario de entradas. La forma más simple de pasar los datos es convertir el DataFrame en diccionario y pasar el diccionario como argumento x a Model.fit:

history = model.fit(dict(df), target, epochs=5, batch_size=BATCH_SIZE)

También funciona con tf.data:

ds = tf.data.Dataset.from_tensor_slices(( dict(df), target )) ds = ds.batch(BATCH_SIZE)
import pprint for x, y in ds.take(1): pprint.pprint(x) print() print(y)
history = model.fit(ds, epochs=5)