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

Classificar dados estruturados usando camadas de pré-processamento do Keras

Este tutorial demonstra como classificar dados estruturados, como dados tabulados, usando uma versão simplificada do dataset PetFinder de uma competição do Kaggle armazenado em um arquivo CSV.

Você usará o Keras para definir o modelo e camadas de pré-processamento do Keras como uma ponte a fim de mapear colunas de um arquivo CSV para características usadas para treinar o modelo. O objetivo é prever se um animal doméstico será adotado.

Este tutorial contém o código completo para:

  • Carregar um arquivo CSV em um DataFrame usando o pandas.

  • Criar um pipeline de entrada para dividir as linhas em lotes e misturá-las usando tf.data. (Confira mais detalhes em tf.data: Criar pipelines de entrada do TensorFlow.)

  • Mapear as colunas no arquivo CSV para características usadas a fim de treinar o modelo utilizando as camadas de pré-processamento do Keras.

  • Criar, treinar e avaliar um modelo usando os métodos integrados do Keras.

Observação: este tutorial é similar ao tutorial Classificar dados estruturados com colunas de características. Esta versão usa as camadas de pré-processamento do Keras em vez da API tf.feature_column, pois elas são mais intuitivas e é fácil incluí-las dentro do modelo para simplificar o desenvolvimento.

Dataset PetFinder.my reduzido

Há milhares de linhas no arquivo CSV do dataset PetFinder.my reduzido, em que cada linha representa um animal doméstico (cachorro ou gato), e cada coluna representa um atributo, como idade, raça, cor e assim por diante.

No resumo do dataset abaixo, observe que há colunas numéricas e de categoria, em sua maioria. Neste tutorial, usaremos somente esses dois tipos de característica, descartando Description (descrição, uma característica com texto livre) e AdoptionSpeed (rapidez de adoção, uma característica de classificação) durante o pré-processamento dos dados.

ColunaDescrição do animal domésticoTipo de característicaTipo de dado
TypeTipo de animal (Dog – cachorro, Cat – gato)CategoriaString
AgeIdadeNúmeroInteiro
Breed1Raça principalCategoriaString
Color1Cor 1CategoriaString
Color2Cor 2CategoriaString
MaturitySizeTamanho quando adultoCategoriaString
FurLengthTamanho dos pelosCategoriaString
VaccinatedSe o animal doméstico foi vacinadoCategoriaString
SterilizedSe o animal doméstico foi castradoCategoriaString
HealthEstado de saúdeCategoriaString
FeeTaxa de adoçãoNúmeroInteiro
DescriptionDescrição do perfilTextoString
PhotoAmtTotal de fotos carregadasNúmeroInteiro
AdoptionSpeedRapidez de adoçãoClassificaçãoInteiro

Importar o TensorFlow e outras bibliotecas

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

Carregar o dataset em um DataFrame do pandas

O pandas é uma biblioteca do Python com diversos utilitários muito úteis para carregar dados estruturados e trabalhar com eles. Use tf.keras.utils.get_file para baixar e extrair o arquivo CSV com o dataset PetFinder.my reduzido e carregá-lo em um DataFrame com 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)

Verifique as primeiras cinco linhas do DataFrame para avaliar o dataset:

dataframe.head()

Criar uma variável alvo

A tarefa original da competição de previsão de adoção do Kaggle era prever a rapidez de adoção de um animal doméstico (por exemplo, na primeira semana, no primeiro mês, nos primeiros três meses, e assim por diante).

Neste tutorial, simplificaremos a tarefa para um problema de classificação binária, em que você somente precisa prever se um animal doméstico foi adotado ou não.

Após modificarmos a coluna AdoptionSpeed, 0 indicará que o animal doméstico não foi adotado, e 1 indicará que foi.

# 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 o DataFrame em conjuntos de treinamento, validação e teste

O dataset é um único DataFrame do pandas. Vamos dividi-lo em conjuntos de treinamento, validação e teste usando, por exemplo, uma proporção de 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')

Criar um pipeline de entrada usando tf.data

Agora, crie uma função utilitária que converta cada DataFrame de treinamento, validação e teste em um tf.data.Dataset, depois misture os dados e divida-os em lotes.

Observação: ao usar um arquivo CSV muito grande (tão grande que não caiba na memória), usaríamos a API tf.data para ler no disco diretamente. Esse processo não é discutido neste 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

Agora, use a função (df_to_dataset) recém-criada para verificar o formato dos dados retornados pela função helper do pipeline de entrada, chamando-a nos dados de treinamento, e use um tamanho pequeno para o lote a fim de manter a saída fácil de ler:

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 )

Conforme demonstrado pela saída, o conjunto de treinamento retorna um dicionário de nomes de colunas (do DataFrame) que faz o mapeamento das linhas para valores de coluna.

Aplicar as camadas de pré-processamento do Keras

Com as camadas de pré-processamento do Keras, você pode criar pipelines de entrada nativos do Keras que podem ser usados ​​como código de pré-processamento independente em outros workflows (que não usam Keras), combinados diretamente com modelos Keras e exportados como parte de um Keras SavedModel.

Neste tutorial, você usará as quatro camadas de pré-processamento abaixo para demonstrar como fazer o pré-processamento, a codificação de dados estruturados e a engenharia de características:

  • tf.keras.layers.Normalization: executa uma normalização das características de entrada.

  • tf.keras.layers.CategoryEncoding: transforma características de categoria representadas por inteiros em representações one-hot, multi-hot ou tf-idf densas.

  • tf.keras.layers.StringLookup: transforma valores de categoria representados por strings em índices inteiros.

  • tf.keras.layers.IntegerLookup: transforma valores de categoria representados por inteiros em índices inteiros.

Saiba mais sobre as camadas disponíveis no guia Como usar camadas de pré-processamento.

  • Para características numéricas do dataset PetFinder.my reduzido, você usará uma camada tf.keras.layers.Normalization para padronizar a distribuição dos dados.

  • Para características de categoria, como Type (Tipo) (strings Dog – cachorro e Cat – gato), você as transformará em tensores com codificação multi-hot usando tf.keras.layers.CategoryEncoding.

Colunas numéricas

Para cada característica numérica do dataset PetFinder.my reduzido, você usará uma camada tf.keras.layers.Normalization para padronizar a distribuição dos dados.

Defina uma nova função utilitária que retorne uma camada que aplique uma normalização de características numéricas usando a camada de pré-processamento do Keras:

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

Em seguida, para testar a nova a função, chame-a nas características de total de fotos do animal doméstico carregadas para normalizar 'PhotoAmt':

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

Observação: se houver muitas características numéricas (centenas ou mais), é mais eficiente concatená-las primeiro e usar uma única camada tf.keras.layers.Normalization.

Colunas de categoria

O Type (Tipo) de animal doméstico é representado como string no dataset – Dog (cachorro) e Cat (gato), que precisa sofrer codificação multi-hot antes de ser alimentado no modelo. A característica Age (idade)

Defina mais uma função utilitária que retorne um camada que mapeie valores de um vocabulário para índices inteiros e faça a codificação multi-hot das características usando as camadas de pré-processamento tf.keras.layers.StringLookup, tf.keras.layers.IntegerLookup e 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))

Para testar a função get_category_encoding_layer, chame-a nas características 'Type' do animal doméstico para transformá-las em tensores com codificação multi-hot:

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 o processo para as características 'Age' do animal doméstico:

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)

Pré-processar determinadas características para treinar o modelo

Você aprendeu a usar diversos tipos de camada de pré-processamento do Keras. Agora você vai:

  • Aplicar as funções utilitárias de pré-processamento definidas anteriormente em 13 características numéricas e de categoria do dataset PetFinder.my reduzido.

  • Adicionar todas as características de entrada a uma lista.

Conforme mencionado no começo, para treinar o modelo, usaremos as características numéricas ('PhotoAmt', 'Fee') e de categoria ('Age', 'Type', 'Color1', 'Color2', 'Gender', 'MaturitySize', 'FurLength', 'Vaccinated', 'Sterilized', 'Health', 'Breed1') do dataset PetFinder.my reduzido.

Observação: se o seu objetivo é criar um modelo exato, experimente usar um dataset maior e pense com cuidado em quais características são as mais importantes a serem incluídas e como devem ser representadas.

Anteriormente, usamos um tamanho pequeno para o lote a fim de demonstrar o pipeline de entrada. Agora, vamos criar um novo pipeline de entrada com um tamanho maior para o lote, igual a 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)

Normalize as características numéricas (o número de fotos e a taxa de adoção do animal doméstico) e adicione-as a uma lista de entradas chamada 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)

Transforme os valores inteiros de categoria do dataset (a idade do animal doméstico) em índices inteiros, faça a codificação multi-hot e adicione as 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 o mesmo passo para os valores de categoria representados por strings:

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)

Criar, compilar e treinar o modelo

O próximo passo é criar um modelo usando a API Functional do Keras. Para a primeira camada do modelo, combine a lista de entradas de característica — encoded_features — em um vetor por meio da concatenação com 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 o modelo com Model.compile do Keras:

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

Vamos conferir o grafo de conectividade:

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

Agora, vamos treinar e testar o modelo:

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

Fazer inferência

Agora, o modelo desenvolvido pode classificar uma linha de um arquivo CSV diretamente após a inclusão das camadas de pré-processamento dentro do modelo.

Agora você pode salvar e recarregar o modelo do Keras usando Model.save e Model.load_model antes de fazer a inferência para novos dados:

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

Para fazer uma previsão para uma nova amostra, basta chamar o método Model.predict do Keras. Você só precisa fazer duas ações:

  1. Encapsular escalares em uma lista para ter uma dimensão de lote (Model processa somente lotes de dados, não amostras individuais).

  2. Chamar tf.convert_to_tensor em 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) )

Observação: geralmente, você terá resultados melhores com aprendizado profundo ao usar datasets muito maiores e mais complexos. Ao utilizar um dataset pequeno, como o PetFinder.my reduzido, você pode usar uma árvore de decisão ou uma floresta aleatória como linha de base. O objetivo deste tutorial é demonstrar a mecânica ao trabalhar com dados estruturados para que você tenha um ponto de partida ao trabalhar com seus próprios datasets no futuro.

Próximos passos

Para saber mais sobre a classificação de dados estruturados, use outros datasets. Para aumentar a exatidão durante o treinamento e teste dos modelos, pense com cuidado em quais características você incluirá no modelo e como elas serão representadas.

Sugerimos alguns datasets:

  • Datasets do TensorFlow: MovieLens: conjunto de avaliações de filmes de um serviço de recomendação de filmes.

  • Datasets do TensorFlow: Wine Quality: dois datasets relacionados a vinhos tinto e branco da vinícola portuguesa "Vinho Verde". O dataset Red Wine Quality (qualidade de vinhos tinto) também está disponível no Kaggle.

  • Kaggle: dataset arXiv: corpus com 1,7 milhão de artigos acadêmicos do arXiv, que abrangem física, ciência da computação, matemática, estatística, engenharia elétrica, biologia quantitativa e economia.