Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/pt-br/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.

Carregue um DataFrame do pandas

Este tutorial fornece exemplos de como carregar DataFrames do pandas no TensorFlow.

Você usará um pequeno dataset de cardiopatia oferecido pelo UCI Machine Learning Repository (Repositório de Aprendizado de Máquina da UCI). Há centenas de linhas no CSV. Cada linha representa um paciente, e cada coluna descreve uma característica. Você usará essas informações para prever se um paciente tem cardiopatia, o que é uma tarefa de classificação binária.

Leia os dados usando o pandas

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

Baixe o arquivo CSV com o dataset de cardiopatia:

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

Leia o arquivo CSV usando o pandas:

df = pd.read_csv(csv_file)

É assim que os dados aparecem:

df.head()
df.dtypes

Você criará modelos para prever o rótulo contido na coluna target.

target = df.pop('target')

Um DataFrame como array

Caso seus dados tenham um datatype uniforme, ou dtype, você poderá usar um DataFrame do pandas em qualquer lugar que seja possível usar um array do NumPy. Isso funciona porque a classe pandas.DataFrame é compatível com o protocolo __array__, e a função tf.convert_to_tensor do TensorFlow aceita objetos compatíveis com o protocolo.

Obtenha as características numéricas do dataset (pule as características categóricas por enquanto):

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

O DataFrame pode ser convertido para um array do NumPy usando a propriedade DataFrame.values ou numpy.array(df). Para convertê-lo em um tensor, use tf.convert_to_tensor:

tf.convert_to_tensor(numeric_features)

Em geral, se um objeto pode ser convertido em um tensor com tf.convert_to_tensor, ele pode ser passado como argumento em qualquer lugar que aceite um tf.Tensor.

Com Model.fit

Um DataFrame, interpretado como um único tensor, pode ser usado diretamente como um argumento para o método Model.fit.

Confira abaixo um exemplo do treinamento de um modelo nas características numéricas de um dataset.

A primeira etapa é normalizar os intervalos de entrada. Use uma camada tf.keras.layers.Normalization para isso.

Para definir a média e o desvio padrão de uma camada antes de executá-la, chame o método Normalization.adapt:

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

Chame a camada nas primeiras três linhas do DataFrame para visualizar um exemplo da saída dessa camada:

normalizer(numeric_features.iloc[:3])

Use a camada de normalização como a primeira camada de um modelo simples:

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

Ao passar o DataFrame como o argumento x para Model.fit, o Keras trata o DataFrame como faria com um array do NumPy:

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

Com tf.data

Se você quiser aplicar transformações tf.data a um DataFrame de dtype uniforme, o método Dataset.from_tensor_slices criará um dataset que itera as linhas do DataFrame. Cada linha é inicialmente um vetor de valores. Para treinar um modelo, você precisa de pares (inputs, labels), então passe (features, labels), e Dataset.from_tensor_slices retornará os pares de fatias:

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)

Um DataFrame como dicionário

Quando você começa a lidar com dados heterogêneos, não é mais possível tratar o DataFrame como um único array. Os tensores do TensorFlow exigem que todos os elementos tenham o mesmo dtype.

Portanto, nesse caso, você precisa começar a tratá-lo como um dicionário de colunas, em que cada coluna tem um dtype uniforme. Um DataFrame é bastante parecido com um dicionário de arrays, então, geralmente você só precisa fazer o casting do DataFrame para um dict do Python. Várias APIs importantes do TensorFlow são compatíveis com dicionários (aninhados) de arrays como entradas.

Os pipelines de entrada do tf.data lidam com isso muito bem. Todas as operações do tf.data lidam com dicionários e tuplas automaticamente. Portanto, para criar um dataset de exemplos de dicionário a partir de um DataFrame, basta fazer o casting para um dict antes de fatiar com Dataset.from_tensor_slices:

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

Aqui estão os três primeiros exemplos desse dataset:

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

Dicionários com o Keras

Geralmente, os modelos e as camadas do Keras esperam um único tensor de entrada, mas essas classes podem aceitar e retornar estruturas aninhadas de dicionários, tuplas e tensores. Essas estruturas são conhecidas como "ninhos" (consulte o módulo tf.nest para mais detalhes).

Há duas maneiras equivalentes de escrever um modelo do Keras que aceita um dicionário como entrada.

1. O estilo subclasse do modelo

Você escreve uma subclasse do tf.keras.Model (ou tf.keras.Layer). Você lida diretamente com as entradas e cria as saídas:

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)

Esse modelo pode aceitar um dicionário de colunas ou um dataset de elementos de dicionário para treinamento:

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)

Aqui estão as previsões para os três primeiros exemplos:

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

2. O estilo funcional do 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)

Você pode treinar o modelo funcional da mesma maneira que a subclasse do modelo:

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)

Exemplo completo

Se você passar um DataFrame heterogêneo para o Keras, cada coluna pode precisar de pré-processamento único. Você pode fazer esse pré-processamento diretamente no DataFrame, mas, para um modelo funcionar corretamente, as entradas precisam ser pré-processadas da mesma maneira. Então, a melhor abordagem é integrar o pré-processamento ao modelo. As camadas de pré-processamento do Keras abrangem várias tarefas comuns.

Crie o head de pré-processamento

Nesse dataset, algumas das características de "número inteiro" nos dados brutos são, na verdade, índices categóricos. Esses índices não são valores numéricos ordenados (confira mais detalhes na descrição do dataset). Como eles não são ordenados, são inadequados para alimentar o modelo diretamente, já que seriam interpretados como ordenados. Para usar essas entradas, será necessário codificá-las, como vetores one-hot ou vetores de embeddings. O mesmo se aplica a características categóricas de strings.

Observação: se você tiver várias características que precisam de pré-processamento idêntico, é mais eficiente concatená-las antes de aplicar o pré-processamento.

Por outro lado, as características binárias geralmente não precisam ser codificadas ou normalizadas.

Comece criando uma lista de características que se enquadram em cada grupo:

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

O próximo passo é criar um modelo de pré-processamento para aplicar o pré-processamento adequado a cada entrada e concatenar os resultados.

Esta seção usa a API Keras Functional para implementar o pré-processamento. Comece criando um tf.keras.Input para cada coluna do 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, você aplicará algumas transformações usando camadas do Keras e operações do TensorFlow. Cada característica começa como um lote de escalares (shape=(batch,)). A saída para cada uma deve ser um lote de vetores tf.float32 (shape=(batch, n)). A última etapa será concatenar todos esses vetores.

Entradas binárias

Como as entradas binárias não precisam de pré-processamento, basta adicionar o eixo do vetor, fazer o casting para float32 e adicioná-las à lista de entradas pré-processadas:

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

Como na seção anterior, execute essas entradas numéricas em uma camada tf.keras.layers.Normalization antes de usá-las. A diferença é que, dessa vez, elas são inseridas como um dict. O código abaixo coleta, empilha e passa as características numéricas do DataFrame para o método Normalization.adapt.

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

O código abaixo empilha e executa as características numéricas na camada de normalização.

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 as características categóricas, primeiro você precisará codificá-las em vetores ou embeddings binários. Como essas características só contêm um número pequeno de categorias, converta as entradas diretamente para vetores one-hot usando a opção output_mode='one_hot', compatível com as camadas tf.keras.layers.StringLookup e tf.keras.layers.IntegerLookup.

Confira um exemplo de como essas camadas funcionam:

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 o vocabulário de cada entrada, crie uma camada para converter esse vocabulário em um vetor one-hot:

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)

Monte o head de pré-processamento

Neste ponto, preprocessed é só uma lista do Python com todos os resultados do pré-processamento, cada um com o formato (batch_size, depth):

preprocessed

Concatene todas as características pré-processadas no eixo depth, para converter cada exemplo de dicionário em um único vetor. O vetor contém características categóricas, numéricas e one-hot categóricas:

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

Agora, crie um modelo a partir desse cálculo para que possa ser reutilizado:

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

Para testar o pré-processador, use o accessor DataFrame.iloc para fatiar o primeiro exemplo do DataFrame. Em seguida, faça a conversão para um dicionário e passe o dicionário para o pré-processador. O resultado é um único vetor com as características binárias, numéricas normalizadas e categóricas one-hot, nessa ordem:

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

Crie e treine um modelo

Agora crie o corpo principal do modelo. Use a mesma configuração que o exemplo anterior: algumas camadas lineares retificadas Dense e uma camada de saída Dense(1) para a classificação.

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

Junte as duas partes usando a API funcional do 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'])

Esse modelo espera um dicionário de entradas. A maneira mais simples de passar os dados é converter o DataFrame em um dict e passar esse dict como o argumento x para Model.fit:

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

Usar tf.data também funciona:

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)