Path: blob/master/site/pt-br/tutorials/load_data/csv.ipynb
25118 views
Copyright 2019 The TensorFlow Authors.
Carregando dados em CSV
Este tutorial fornece exemplos de como usar dados CSV com o TensorFlow.
Esse processo consiste de duas partes:
Carregar os dados do disco
Pré-processar os dados em formato adequado para treinamento.
Este tutorial foca no carregamento e fornece alguns exemplos rápidos de pré-processamento. Para saber mais sobre o aspecto de pré-processamento, veja o guia Trabalhando com camadas de pré-processamento e o tutorial Classificando dados estruturados com camadas de pré-processamento Keras.
Configuração
Dados na memória
Para qualquer pequeno dataset em CSV, a maneira mais simples de treinar um modelo TensorFlow nele é carregá-lo na memória como um Dataframe pandas ou um array NumPy.
Um exemplo relativamente simples é o dataset abalone .
O dataset é pequeno.
Todas as características de entrada são valores de ponto flutuante de faixa limitada.
Eis como baixar os dados num DataFrame
do pandas:
O dataset contém um conjunto de medições de abalone, um tipo de caracol marinho.
“Casca de abalone” (por Nicki Dugan Pogue, CC BY-SA 2.0)
A tarefa nominal para este dataset é prever a idade a partir de outras medidas, então separe as características e rótulos para treinamento:
Para este dataset, você tratará todos os recursos de forma idêntica. Agrupe os recursos num único array NumPy.:
Em seguida, crie um modelo de regressão para prever a idade. Como existe apenas um único tensor de entrada, um modelo tf.keras.Sequential
é suficiente aqui.
Para treinar esse modelo, passe os recursos e rótulos para Model.fit
:
Você acabou de ver a maneira mais básica de treinar um modelo usando dados CSV. A seguir, você aprenderá como aplicar o pré-processamento para normalizar colunas numéricas.
Pré-processamento básico
É uma boa prática normalizar as entradas do seu modelo. As camadas de pré-processamento Keras fornecem uma maneira conveniente de incorporar essa normalização em seu modelo.
A camada tf.keras.layers.Normalization
pré-calcula a média e a variância de cada coluna e as usa para normalizar os dados.
Primeiro, crie a camada:
Em seguida, use o método Normalization.adapt
para adaptar a camada de normalização aos seus dados.
Observação: use apenas seus dados de treinamento com o método PreprocessingLayer.adapt
. Não use seus dados de validação ou teste.
Em seguida, use a camada de normalização no seu modelo:
Tipos de dados mistos
O dataset "Titanic" contém informações sobre os passageiros do Titanic. A tarefa nominal neste dataset é prever quem sobreviveu.
Imagem da Wikimedia
Os dados brutos podem ser facilmente carregados como um DataFrame
do Pandas, mas não podem ser usados imediatamente como entrada para um modelo do TensorFlow.
Devido aos diferentes tipos e intervalos de dados, você não pode simplesmente empilhar as características numa matriz NumPy e passá-las para um modelo tf.keras.Sequential
. Cada coluna precisa ser tratada individualmente.
Como opção, você pode pré-processar seus dados off-line (usando qualquer ferramenta de sua preferência) para converter colunas categóricas em colunas numéricas e, em seguida, passar a saída processada para seu modelo do TensorFlow. A desvantagem dessa abordagem é que se você salvar e exportar seu modelo, o pré-processamento não será salvo com ele. As camadas de pré-processamento do Keras evitam esse problema porque fazem parte do modelo.
Neste exemplo, você construirá um modelo que implementa a lógica de pré-processamento usando a API funcional Keras. Você também pode fazer isso através de uma subclasse.
A API funcional opera sobre tensores "simbólicos". Tensores normais "eager" têm um valor. Em contraste, esses tensores “simbólicos” não têm. Em vez disso, eles controlam quais operações são executadas neles e constroem uma representação do cálculo, que você pode executar posteriormente. Aqui está um exemplo rápido:
Para construir o modelo de pré-processamento, comece construindo um conjunto de objetos tf.keras.Input
simbólicos, correspondendo aos nomes e tipos de dados das colunas do CSV.
O primeiro passo na sua lógica de pré-processamento é concatenar as entradas numéricas e executá-las por meio de uma camada de normalização:
Junte todos os resultados do pré-processamento simbólico, para concatená-los posteriormente:
Para as entradas que são strings, use a função tf.keras.layers.StringLookup
para mapear de strings para índices inteiros num vocabulário. Em seguida, use tf.keras.layers.CategoryEncoding
para converter os índices em dados float32
apropriados para o modelo.
As configurações padrão para a camada tf.keras.layers.CategoryEncoding
criam um vetor one-hot para cada entrada. Um tf.keras.layers.Embedding
também funcionaria. Confira o guia Trabalhando com camadas de pré-processamento e o tutorial Classificando dados estruturados usando camadas de pré-processamento do Keras para mais informações sobre este tópico.
Com a coleção de inputs
e preprocessed_inputs
, você pode concatenar todas as entradas pré-processadas e construir um modelo que cuide do pré-processamento:
Este modelo contém apenas o pré-processamento da entrada. Você pode executá-lo para ver o que ele faz com seus dados. Os modelos do Keras não convertem automaticamente objetos DataFrame
do Pandas porque não está claro se eles devem ser convertidos em tensores ou em dicionários de tensores. Então, converta-o num dicionário de tensores:
Divida o primeiro exemplo de treinamento e passe-o para este modelo de pré-processamento. Você verá as características numéricas e as strings one-hots, todas concatenadas:
Agora, construa o modelo em cima disso:
Ao treinar o modelo, passe o dicionário de características como x
e o rótulo como y
.
Já que o pré-processamento faz parte do modelo, você pode salvar o modelo e recarregá-lo noutro lugar e obter resultados idênticos:
Usando tf.data
Na seção anterior, você contou com o embaralhamento e agrupamento em lote de dados integrados do modelo durante o treinamento.
Se você precisar de mais controle sobre o pipeline de dados de entrada ou precisar usar dados que não cabem facilmente na memória: use tf.data
.
Para mais exemplos, consulte o guia tf.data
: criando pipelines de entrada do TensorFlow.
Com dados na memória
Como um primeiro exemplo da aplicação de tf.data
a dados CSV, considere o código a seguir para dividir manualmente o dicionário de características da seção anterior. Para cada índice, é necessário usar aquele índice para cada característica:
Execute e imprima o primeiro exemplo:
O mais simples carregador de dados tf.data.Dataset
na memória é o construtor Dataset.from_tensor_slices
. Ele retorna um tf.data.Dataset
que implementa uma versão generalizada da função slices
acima, no TensorFlow.
Você pode iterar sobre um tf.data.Dataset
como qualquer outro objeto Python iterável:
A função from_tensor_slices
pode lidar com qualquer estrutura de dicionários ou tuplas aninhadas. O código a seguir cria um dataset de pares (features_dict, labels)
:
Para treinar um modelo usando este Dataset
, você precisará de pelo menos fazer shuffle
(embaralhar) e batch
(colocar em lote) sobre os dados.
Em vez de passar features
e labels
para Model.fit
, você passa o dataset:
De um único arquivo
Até agora, este tutorial funcionou com dados na memória. tf.data
é um kit de ferramentas altamente escalável para construir pipelines de dados e fornece algumas funções para lidar com o carregamento de arquivos em CSV.
Agora leia os dados CSV do arquivo e crie um tf.data.Dataset
.
(Para a documentação completa, consulte tf.data.experimental.make_csv_dataset
)
Esta função inclui diversos recursos convenientes, para que fique fácil trabalhar com os dados. Isto inclui:
O uso dos cabeçalhos das colunas como chaves de dicionário.
Determinando automaticamente o tipo de cada coluna.
Atenção: certifique-se de definir o argumento num_epochs
em tf.data.experimental.make_csv_dataset
, caso contrário, o comportamento padrão para tf.data.Dataset
é fazer um loop infinito.
Observação: Se você executar a célula acima duas vezes, produzirá resultados diferentes. As configurações padrão para tf.data.experimental.make_csv_dataset
incluem shuffle_buffer_size=1000
, que é mais que suficiente para este pequeno dataset, mas pode não ser para um dataset do mundo real.
Isto também pode ser usado para descompactar os dados instantaneamente. Aqui está um arquivo CSV compactado contendo o dataset de tráfego interestadual metropolitano.
Imagem da Wikimedia
Defina o argumento compression_type
para ler diretamente do arquivo compactado:
Observação: se precisar analisar essas strings de data e hora no pipeline tf.data
, você poderá usar tfa.text.parse_time
.
Cache
Existe algum overhead no processamento dos dados em formato CSV. Para modelos pequenos este pode ser o gargalo do treinamento.
Dependendo do seu caso de uso, pode ser uma boa ideia usar Dataset.cache
ou tf.data.Dataset.snapshot
, para que os dados CSV sejam processados apenas na primeira época.
A principal diferença entre os métodos de cache
e snapshot
é que os arquivos cache
só podem ser usados pelo processo do TensorFlow que os criou, mas os arquivos snapshot
podem ser lidos por outros processos.
Por exemplo, iterar sobre traffic_volume_csv_gz_ds
20 vezes pode levar cerca de 15 segundos sem armazenamento em cache ou cerca de dois segundos com armazenamento em cache.
Observação: Dataset.cache
armazena os dados da primeira época e os reproduz em ordem. Portanto, usar o método cache
desativa qualquer embaralhamento anterior no pipeline. Abaixo, Dataset.shuffle
é adicionado novamente após Dataset.cache
.
Observação: Os arquivos tf.data.Dataset.snapshot
destinam-se ao armazenamento temporário de um dataset durante o uso. Este não é um formato para armazenamento de longo prazo. O formato do arquivo é considerado um detalhe interno e não é garantido entre versões do TensorFlow.
Se o carregamento de dados for retardado pelo carregamento de arquivos CSV e Dataset.cache
e tf.data.Dataset.snapshot
forem insuficientes para seu caso de uso, considere recodificar seus dados num formato mais simplificado.
Múltiplos arquivos
Todos os exemplos até agora nesta seção poderiam ser realizados facilmente sem tf.data
. Um lugar onde tf.data
pode realmente simplificar as coisas é ao lidar com coleções de arquivos.
Por exemplo, o dataset de imagens de fontes de caracteres é distribuído como uma coleção de arquivos csv, um arquivo por fonte.
Imagem por Willi Heidelbach do Pixabay
Baixe o dataset e revise os arquivos contidos nele:
Ao lidar com muitos arquivos, você pode passar um file_pattern
estilo glob para a função tf.data.experimental.make_csv_dataset
. A ordem dos arquivos é embaralhada a cada iteração.
Use o argumento num_parallel_reads
para definir quantos arquivos são lidos em paralelo e intercalados.
Esses arquivos CSV têm as imagens achatadas numa única linha. Os nomes das colunas são formatados r{row}c{column}
. Aqui está o primeiro lote:
Opcional: empacotando campos
Você provavelmente não vai querer trabalhar com cada pixel em colunas separadas como esta. Antes de tentar usar este dataset, certifique-se de compactar os pixels em um tensor de imagem.
Aqui está o código que analisa os nomes das colunas para construir imagens para cada exemplo:
Aplique essa função a cada lote no dataset:
Plote as imagens resultantes:
Funções de nível inferior
Até o momento, este tutorial tem se concentrado nos utilitários de nível mais alto para leitura de dados em formato CSV. Existem outras duas APIs que podem ser úteis para usuários avançados se o seu caso de uso não se enquadrar nos padrões básicos.
tf.io.decode_csv
: uma função para processar linhas de texto numa lista de tensores de coluna CSV.tf.data.experimental.CsvDataset
: um construtor de datasets CSV de nível inferior.
Esta seção recria a funcionalidade fornecida por tf.data.experimental.make_csv_dataset
, para demonstrar como essa funcionalidade de nível inferior pode ser usada.
tf.io.decode_csv
Esta função decodifica uma string ou lista de strings em uma lista de colunas.
Ao contrário de tf.data.experimental.make_csv_dataset
esta função não tenta adivinhar os tipos de dados da coluna. Você especifica os tipos de coluna fornecendo uma lista de record_defaults
contendo um valor do tipo correto, para cada coluna.
Para ler os dados do Titanic como strings usando tf.io.decode_csv
você faria:
Para processá-los com seus tipos reais, crie uma lista de record_defaults
dos tipos correspondentes:
Observação: É mais eficiente chamar tf.io.decode_csv
em grandes lotes de linhas do que em linhas individuais de texto CSV.
tf.data.experimental.CsvDataset
A classe tf.data.experimental.CsvDataset
fornece uma interface CSV Dataset
mínima sem os recursos convenientes da função tf.data.experimental.make_csv_dataset
: análise de cabeçalho de coluna, inferência de tipo de coluna, embaralhamento automático, intercalação de arquivos.
Este construtor usa record_defaults
da mesma forma que tf.io.decode_csv
:
O código acima é praticamente equivalente a:
Múltiplos arquivos
Para processar o dataset de fontes usando tf.data.experimental.CsvDataset
, primeiro você precisa determinar os tipos de coluna para record_defaults
. Comece inspecionando a primeira linha de um arquivo:
Apenas os dois primeiros campos são strings, os restantes são inteiros ou flutuantes, e você pode obter o número total de características contando as vírgulas:
O construtor tf.data.experimental.CsvDataset
pode receber uma lista de arquivos de entrada, mas vai lê-los sequencialmente. O primeiro arquivo na lista de CSVs é AGENCY.csv
:
Assim, ao passar a lista de arquivos para CsvDataset
, os registros de AGENCY.csv
são lidos primeiro:
Para intercalar múltiplos arquivos, use Dataset.interleave
.
Eis um dataset inicial que contém os nomes dos arquivos CSV:
Isto embaralha os nomes dos arquivos em cada época:
O método interleave
usa um map_func
que cria um Dataset
filho para cada elemento do Dataset
pai.
Aqui, você vai querer criar um tf.data.experimental.CsvDataset
a partir de cada elemento do dataset de arquivos:
O Dataset
retornado por interleave retorna elementos percorrendo vários objetos Dataset
filhos. Observe, abaixo, como o dataset percorre três arquivos de fonte (cycle_length=3
):
Desempenho
Anteriormente, foi observado que tf.io.decode_csv
é mais eficiente quando executado num lote de strings.
É possível tomar proveito desse fato, ao usar lotes grandes, para melhorar o desempenho do carregamento de CSV (mas tente primeiro armazenar em cache).
Com o carregador integrado 20 lotes de 2.048 exemplos levam cerca de 17s.
Passar lotes de linhas de texto para decode_csv
é mais rápido, em cerca de 5s:
Para outro exemplo de como aumentar o desempenho do CSV usando lotes grandes, consulte o tutorial sobre overfit e underfit.
Esse tipo de abordagem pode funcionar, mas considere outras opções como Dataset.cache
e tf.data.Dataset.snapshot
ou recodificar seus dados num formato mais simplificado.