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

Classificar dados estruturados com colunas de características

Aviso: o módulo tf.feature_columns descrito neste tutorial não é recomendado para novos códigos. As camadas de pré-processamento do Keras abrangem essa funcionalidade. Para instruções de como migrar, confira o Guia de migração das colunas de características. O módulo tf.feature_columns foi feito para ser usado com Estimadores do TF1. Ele é abarcado pelas garantias de compatibilidade, mas não recebe mais correções, exceto para vulnerabilidades de segurança.

Este tutorial demonstra como classificar dados estruturados (por exemplo, dados tabulados em um CSV). Usaremos o Keras para definir o modelo e tf.feature_column como uma ponte para mapear as colunas em um CSV para características usadas a fim de treinar o modelo. Este tutorial contém o código completo para:

  • Carregar um arquivo CSV usando o Pandas.

  • Criar um pipeline de entrada para dividir as linhas em lotes e misturá-las usando tf.data.

  • Mapear as colunas no CSV para características usadas a fim de treinar o modelo utilizando colunas de características.

  • Criar, treinar e avaliar um modelo usando o Keras.

Dataset

Usaremos uma versão simplificada do dataset PetFinder. Há milhares de linhas no CSV. Cada linha representa um animal doméstico, e cada coluna representa um atributo. Usaremos essas informações para prever com que rapidez o animal doméstico será adotado.

Veja abaixo uma descrição do dataset. Observe que existem colunas numéricas e de categorias. Há uma coluna de texto livre, que não será usada neste tutorial.

ColunaDescriçãoTipo de característicaTipo de dado
TypeTipo de animal (cachorro, gato)Categoriastring
AgeIdade do animal domésticoNúmerointeiro
Breed1Raça principal do animal domésticoCategoriastring
Color1Cor 1 do animal domésticoCategoriastring
Color2Cor 2 do animal domésticoCategoriastring
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 perfil deste animal domésticoTextostring
PhotoAmtTotal de fotos carregadas deste animal domésticoNúmerointeiro
AdoptionSpeedRapidez de adoçãoClassificaçãointeiro

Importar o TensorFlow e outras bibliotecas

!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 o Pandas para criar um dataframe

O Pandas é uma biblioteca do Python com diversos utilitários muito úteis para carregar dados estruturados e trabalhar com eles. Usaremos o Pandas para baixar o dataset de uma URL e carregá-lo em um 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()

Criar a variável alvo

A tarefa do dataset original é 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). Vamos simplificar para este tutorial – vamos transformar em um problema de classificação binário e apenas prever se o animal doméstico foi adotado ou não.

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

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

O dataset baixado é um único arquivo CSV. Vamos dividi-lo em conjuntos de treinamento, validação e teste.

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')

Criar um pipeline de entrada usando tf.data

Agora, vamos encapsular os dataframes usando tf.data, que nos permitirá usar as colunas de características como uma ponte para mapear as colunas no dataframe do Pandas para características usadas para treinar o modelo. Se estivéssemos usando um arquivo CSV muito grande (tão grande que não coubesse na memória), usaríamos tf.data para ler no disco diretamente. Esse processo não é discutido neste 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)

Sobre o pipeline de entrada

Agora que criamos o pipeline de entrada, vamos chamá-lo para ver o formato dos dados retornados. Usamos um tamanho pequeno para o lote a fim de manter a saída fácil de ler.

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 o dataset retorna um dicionário de nomes de colunas (do dataframe) que faz o mapeamento das linhas para valores de coluna no dataframe.

Demonstração de vários tipos de coluna de características

O TensorFlow fornece diversos tipos de coluna de característica. Nesta seção, vamos criar vários tipos e demonstrar como eles transformam uma coluna do 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())

Colunas numéricas

A saída de uma coluna de característica se torna a entrada do modelo (usando a função de demonstração definida acima, conseguiremos ver exatamente como cada coluna do dataframe é transformada). Uma coluna numérica é o tipo mais simples e é usada para representar características com valores reais. Ao usar essa coluna, seu modelo receberá o valor da coluna do dataframe sem alterações.

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

No dataset PetFinder, a maioria das colunas do dataframe são de categoria.

Coluna em buckets

Geralmente, não alimentamos um número diretamente no modelo. Em vez disso, dividimos o valor em diferentes categorias com base nos intervalos numéricos. Considere os dados brutos que representem a idade de uma pessoa. Em vez de representar a idade como uma coluna numérica, poderíamos dividir a idade em diversos buckets usando uma coluna em buckets. Observe que os valores one-hot abaixo descrevem a qual intervalo de idade cada linha corresponde.

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

Colunas de categoria

Neste dataset, Type (Tipo) é representado como uma string (por exemplo, "dog" – cachorro – ou "cat" – gato). Não podemos alimentar strings diretamente no modelo. Em vez disso, primeiro precisamos mapeá-las para valores numéricos. As colunas de vocabulário de categorias são uma forma de representar strings como um vetor one-hot (similar ao que vimos acima com buckets de idade). O vocabulário pode ser passado como uma lista usando categorical_column_with_vocabulary_list ou carregado de um arquivo 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)

Colunas de embedding

Suponha que, em vez de ter somente algumas strings possíveis, tivéssemos milhares (ou mais) de valores por categoria. Por diversos motivos, à medida que o número de categorias cresce, fica inviável treinar uma rede neural usando codificações one-hot. Podemos usar uma coluna de embedding para superar essa limitação. Em vez de representar os dados como um vetor one-hot com diversas dimensões, uma coluna de embedding representa os dados como um vetor Dense de baixa dimensão, em que cada célula pode conter qualquer número, não apenas 0 ou 1. O tamanho do embedding (8, no exemplo abaixo) é um parâmetro que precisa ser ajustado.

Ponto-chave: usar uma coluna de embedding é a melhor opção quando uma coluna de categoria tiver diversos valores possíveis. Estamos usando uma aqui para fins de demonstração. Dessa forma, você terá um exemplo completo que pode ser modificado para diferentes datasets no 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)

Colunas de características com hash

Outra maneira de representar uma coluna de categorias com um grande número de valores é usando categorical_column_with_hash_bucket. Essa coluna de categorias calcula um valor de hash da entrada, depois seleciona um dos buckets hash_bucket_size para codificar uma string. Ao usar essa coluna, você não precisa fornecer o vocabulário e pode optar por deixar o número de hash_buckets consideravelmente menor do que o número de categorias reais para economizar espaço.

Ponto-chave: uma desvantagem importante desta técnica é que poderá haver colisões, em que strings diferentes são mapeadas para o mesmo bucket. Mesmo assim, na prática, isso pode funcionar bem para alguns datasets.

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

Colunas de características cruzadas

Com a combinação de características em uma só, mais conhecida como cruzamentos de características, um modelo pode aprender pesos separados para cada combinação de características. Aqui, criaremos uma nova característica proveniente do cruzamento de Age (Idade) e Type (Tipo). Observe que crossed_column não cria a tabela completa de todas as possíveis combinações (que seria muito grande). Em vez disso, é utilizada uma coluna hashed_column para você poder escolher o tamanho da tabela.

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

Escolher quais colunas usar

Vimos como usar diversos tipos de coluna de características. Agora, vamos usá-los para treinar um modelo. O objetivo deste tutorial é mostrar o código completo (ou seja, a mecânica) necessário para trabalhar com colunas de características. Selecionamos algumas colunas arbitrariamente para treinar o modelo abaixo.

Ponto-chave: 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.

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))

Criar uma camada de características

Agora que definimos as colunas de características, vamos usar uma camada DenseFeatures como entrada do modelo do Keras.

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

Anteriormente, usamos um tamanho pequeno para o lote a fim de demonstrar o funcionamento das colunas de características. Criamos um novo pipeline de entrada com um tamanho maior para o lote.

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)

Criar, compilar e treinar o 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)

Ponto-chave: geralmente, você observará os melhores resultados com aprendizado profundo ao usar datasets muito maiores e mais complexos. Ao utilizar um dataset pequeno como este, recomendamos usar uma árvore de decisão ou floresta aleatória como linha de base. O objetivo deste tutorial não é treinar um modelo preciso, mas demonstrar a mecânica ao trabalhar com dados estruturados para que você tenha um código que possa ser usado como ponto de partida ao trabalhar com seus próprios datasets no futuro.

Próximos passos

A melhor forma de aprender mais sobre a classificação de dados estruturados é botando a mão na massa. Sugerimos que você encontre outro dataset e treine um modelo para classificá-lo usando um código parecido com o deste tutorial. Para aumentar a exatidão, pense com cuidado em quais características você incluirá no modelo e como elas serão representadas.