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

Carregando dados em CSV

Este tutorial fornece exemplos de como usar dados CSV com o TensorFlow.

Esse processo consiste de duas partes:

  1. Carregar os dados do disco

  2. 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

import pandas as pd import numpy as np # Make numpy values easier to read. np.set_printoptions(precision=3, suppress=True) import tensorflow as tf from tensorflow.keras import layers

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:

abalone_train = pd.read_csv( "https://storage.googleapis.com/download.tensorflow.org/data/abalone_train.csv", names=["Length", "Diameter", "Height", "Whole weight", "Shucked weight", "Viscera weight", "Shell weight", "Age"]) abalone_train.head()

O dataset contém um conjunto de medições de abalone, um tipo de caracol marinho.

an abalone shell

“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:

abalone_features = abalone_train.copy() abalone_labels = abalone_features.pop('Age')

Para este dataset, você tratará todos os recursos de forma idêntica. Agrupe os recursos num único array NumPy.:

abalone_features = np.array(abalone_features) abalone_features

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.

abalone_model = tf.keras.Sequential([ layers.Dense(64, activation='relu'), layers.Dense(1) ]) abalone_model.compile(loss = tf.keras.losses.MeanSquaredError(), optimizer = tf.keras.optimizers.Adam())

Para treinar esse modelo, passe os recursos e rótulos para Model.fit:

abalone_model.fit(abalone_features, abalone_labels, epochs=10)

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:

normalize = layers.Normalization()

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.

normalize.adapt(abalone_features)

Em seguida, use a camada de normalização no seu modelo:

norm_abalone_model = tf.keras.Sequential([ normalize, layers.Dense(64, activation='relu'), layers.Dense(1) ]) norm_abalone_model.compile(loss = tf.keras.losses.MeanSquaredError(), optimizer = tf.keras.optimizers.Adam()) norm_abalone_model.fit(abalone_features, abalone_labels, epochs=10)

Tipos de dados mistos

O dataset "Titanic" contém informações sobre os passageiros do Titanic. A tarefa nominal neste dataset é prever quem sobreviveu.

A traffic jam.

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.

titanic = pd.read_csv("https://storage.googleapis.com/tf-datasets/titanic/train.csv") titanic.head()
titanic_features = titanic.copy() titanic_labels = titanic_features.pop('survived')

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:

# Create a symbolic input input = tf.keras.Input(shape=(), dtype=tf.float32) # Perform a calculation using the input result = 2*input + 1 # the result doesn't have a value result
calc = tf.keras.Model(inputs=input, outputs=result)
print(calc(1).numpy()) print(calc(2).numpy())

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.

inputs = {} for name, column in titanic_features.items(): dtype = column.dtype if dtype == object: dtype = tf.string else: dtype = tf.float32 inputs[name] = tf.keras.Input(shape=(1,), name=name, dtype=dtype) inputs

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:

numeric_inputs = {name:input for name,input in inputs.items() if input.dtype==tf.float32} x = layers.Concatenate()(list(numeric_inputs.values())) norm = layers.Normalization() norm.adapt(np.array(titanic[numeric_inputs.keys()])) all_numeric_inputs = norm(x) all_numeric_inputs

Junte todos os resultados do pré-processamento simbólico, para concatená-los posteriormente:

preprocessed_inputs = [all_numeric_inputs]

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.

for name, input in inputs.items(): if input.dtype == tf.float32: continue lookup = layers.StringLookup(vocabulary=np.unique(titanic_features[name])) one_hot = layers.CategoryEncoding(num_tokens=lookup.vocabulary_size()) x = lookup(input) x = one_hot(x) preprocessed_inputs.append(x)

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:

preprocessed_inputs_cat = layers.Concatenate()(preprocessed_inputs) titanic_preprocessing = tf.keras.Model(inputs, preprocessed_inputs_cat) tf.keras.utils.plot_model(model = titanic_preprocessing , rankdir="LR", dpi=72, show_shapes=True)

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:

titanic_features_dict = {name: np.array(value) for name, value in titanic_features.items()}

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:

features_dict = {name:values[:1] for name, values in titanic_features_dict.items()} titanic_preprocessing(features_dict)

Agora, construa o modelo em cima disso:

def titanic_model(preprocessing_head, inputs): body = tf.keras.Sequential([ layers.Dense(64, activation='relu'), layers.Dense(1) ]) preprocessed_inputs = preprocessing_head(inputs) result = body(preprocessed_inputs) model = tf.keras.Model(inputs, result) model.compile(loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), optimizer=tf.keras.optimizers.Adam()) return model titanic_model = titanic_model(titanic_preprocessing, inputs)

Ao treinar o modelo, passe o dicionário de características como x e o rótulo como y.

titanic_model.fit(x=titanic_features_dict, y=titanic_labels, epochs=10)

Já que o pré-processamento faz parte do modelo, você pode salvar o modelo e recarregá-lo noutro lugar e obter resultados idênticos:

titanic_model.save('test.keras') reloaded = tf.keras.models.load_model('test.keras')
features_dict = {name:values[:1] for name, values in titanic_features_dict.items()} before = titanic_model(features_dict) after = reloaded(features_dict) assert (before-after)<1e-3 print(before) print(after)

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:

import itertools def slices(features): for i in itertools.count(): # For each feature take index `i` example = {name:values[i] for name, values in features.items()} yield example

Execute e imprima o primeiro exemplo:

for example in slices(titanic_features_dict): for name, value in example.items(): print(f"{name:19s}: {value}") break

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.

features_ds = tf.data.Dataset.from_tensor_slices(titanic_features_dict)

Você pode iterar sobre um tf.data.Dataset como qualquer outro objeto Python iterável:

for example in features_ds: for name, value in example.items(): print(f"{name:19s}: {value}") break

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

titanic_ds = tf.data.Dataset.from_tensor_slices((titanic_features_dict, titanic_labels))

Para treinar um modelo usando este Dataset, você precisará de pelo menos fazer shuffle (embaralhar) e batch (colocar em lote) sobre os dados.

titanic_batches = titanic_ds.shuffle(len(titanic_labels)).batch(32)

Em vez de passar features e labels para Model.fit, você passa o dataset:

titanic_model.fit(titanic_batches, epochs=5)

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.

titanic_file_path = tf.keras.utils.get_file("train.csv", "https://storage.googleapis.com/tf-datasets/titanic/train.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)

titanic_csv_ds = tf.data.experimental.make_csv_dataset( titanic_file_path, batch_size=5, # Artificially small to make examples easier to show. label_name='survived', num_epochs=1, ignore_errors=True,)

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.

for batch, label in titanic_csv_ds.take(1): for key, value in batch.items(): print(f"{key:20s}: {value}") print() print(f"{'label':20s}: {label}")

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.

Fonts

Imagem da Wikimedia

traffic_volume_csv_gz = tf.keras.utils.get_file( 'Metro_Interstate_Traffic_Volume.csv.gz', "https://archive.ics.uci.edu/ml/machine-learning-databases/00492/Metro_Interstate_Traffic_Volume.csv.gz", cache_dir='.', cache_subdir='traffic')

Defina o argumento compression_type para ler diretamente do arquivo compactado:

traffic_volume_csv_gz_ds = tf.data.experimental.make_csv_dataset( traffic_volume_csv_gz, batch_size=256, label_name='traffic_volume', num_epochs=1, compression_type="GZIP") for batch, label in traffic_volume_csv_gz_ds.take(1): for key, value in batch.items(): print(f"{key:20s}: {value[:5]}") print() print(f"{'label':20s}: {label[:5]}")

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.

%%time for i, (batch, label) in enumerate(traffic_volume_csv_gz_ds.repeat(20)): if i % 40 == 0: print('.', end='') print()

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.

%%time caching = traffic_volume_csv_gz_ds.cache().shuffle(1000) for i, (batch, label) in enumerate(caching.shuffle(1000).repeat(20)): if i % 40 == 0: print('.', end='') print()

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.

%%time snapshotting = traffic_volume_csv_gz_ds.snapshot('titanic.tfsnap').shuffle(1000) for i, (batch, label) in enumerate(snapshotting.shuffle(1000).repeat(20)): if i % 40 == 0: print('.', end='') print()

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.

A traffic jam.

Imagem por Willi Heidelbach do Pixabay

Baixe o dataset e revise os arquivos contidos nele:

fonts_zip = tf.keras.utils.get_file( 'fonts.zip', "https://archive.ics.uci.edu/ml/machine-learning-databases/00417/fonts.zip", cache_dir='.', cache_subdir='fonts', extract=True)
import pathlib font_csvs = sorted(str(p) for p in pathlib.Path('fonts').glob("*.csv")) font_csvs[:10]
len(font_csvs)

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.

fonts_ds = tf.data.experimental.make_csv_dataset( file_pattern = "fonts/*.csv", batch_size=10, num_epochs=1, num_parallel_reads=20, shuffle_buffer_size=10000)

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:

for features in fonts_ds.take(1): for i, (name, value) in enumerate(features.items()): if i>15: break print(f"{name:20s}: {value}") print('...') print(f"[total: {len(features)} features]")

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:

import re def make_images(features): image = [None]*400 new_feats = {} for name, value in features.items(): match = re.match('r(\d+)c(\d+)', name) if match: image[int(match.group(1))*20+int(match.group(2))] = value else: new_feats[name] = value image = tf.stack(image, axis=0) image = tf.reshape(image, [20, 20, -1]) new_feats['image'] = image return new_feats

Aplique essa função a cada lote no dataset:

fonts_image_ds = fonts_ds.map(make_images) for features in fonts_image_ds.take(1): break

Plote as imagens resultantes:

from matplotlib import pyplot as plt plt.figure(figsize=(6,6), dpi=120) for n in range(9): plt.subplot(3,3,n+1) plt.imshow(features['image'][..., n]) plt.title(chr(features['m_label'][n])) plt.axis('off')

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:

text = pathlib.Path(titanic_file_path).read_text() lines = text.split('\n')[1:-1] all_strings = [str()]*10 all_strings
features = tf.io.decode_csv(lines, record_defaults=all_strings) for f in features: print(f"type: {f.dtype.name}, shape: {f.shape}")

Para processá-los com seus tipos reais, crie uma lista de record_defaults dos tipos correspondentes:

print(lines[0])
titanic_types = [int(), str(), float(), int(), int(), float(), str(), str(), str(), str()] titanic_types
features = tf.io.decode_csv(lines, record_defaults=titanic_types) for f in features: print(f"type: {f.dtype.name}, shape: {f.shape}")

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:

simple_titanic = tf.data.experimental.CsvDataset(titanic_file_path, record_defaults=titanic_types, header=True) for example in simple_titanic.take(1): print([e.numpy() for e in example])

O código acima é praticamente equivalente a:

def decode_titanic_line(line): return tf.io.decode_csv(line, titanic_types) manual_titanic = ( # Load the lines of text tf.data.TextLineDataset(titanic_file_path) # Skip the header row. .skip(1) # Decode the line. .map(decode_titanic_line) ) for example in manual_titanic.take(1): print([e.numpy() for e in example])

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:

font_line = pathlib.Path(font_csvs[0]).read_text().splitlines()[1] print(font_line)

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:

num_font_features = font_line.count(',')+1 font_column_types = [str(), str()] + [float()]*(num_font_features-2)

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:

font_csvs[0]

Assim, ao passar a lista de arquivos para CsvDataset, os registros de AGENCY.csv são lidos primeiro:

simple_font_ds = tf.data.experimental.CsvDataset( font_csvs, record_defaults=font_column_types, header=True)
for row in simple_font_ds.take(10): print(row[0].numpy())

Para intercalar múltiplos arquivos, use Dataset.interleave.

Eis um dataset inicial que contém os nomes dos arquivos CSV:

font_files = tf.data.Dataset.list_files("fonts/*.csv")

Isto embaralha os nomes dos arquivos em cada época:

print('Epoch 1:') for f in list(font_files)[:5]: print(" ", f.numpy()) print(' ...') print() print('Epoch 2:') for f in list(font_files)[:5]: print(" ", f.numpy()) print(' ...')

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:

def make_font_csv_ds(path): return tf.data.experimental.CsvDataset( path, record_defaults=font_column_types, header=True)

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

font_rows = font_files.interleave(make_font_csv_ds, cycle_length=3)
fonts_dict = {'font_name':[], 'character':[]} for row in font_rows.take(10): fonts_dict['font_name'].append(row[0].numpy().decode()) fonts_dict['character'].append(chr(row[2].numpy())) pd.DataFrame(fonts_dict)

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.

BATCH_SIZE=2048 fonts_ds = tf.data.experimental.make_csv_dataset( file_pattern = "fonts/*.csv", batch_size=BATCH_SIZE, num_epochs=1, num_parallel_reads=100)
%%time for i,batch in enumerate(fonts_ds.take(20)): print('.',end='') print()

Passar lotes de linhas de texto para decode_csv é mais rápido, em cerca de 5s:

fonts_files = tf.data.Dataset.list_files("fonts/*.csv") fonts_lines = fonts_files.interleave( lambda fname:tf.data.TextLineDataset(fname).skip(1), cycle_length=100).batch(BATCH_SIZE) fonts_fast = fonts_lines.map(lambda x: tf.io.decode_csv(x, record_defaults=font_column_types))
%%time for i,batch in enumerate(fonts_fast.take(20)): print('.',end='') print()

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.