Carica tfrecord esterno con TFDS

Se hai un protocollo tf.train.Example (all'interno di .tfrecord , .riegeli ,...), che è stato generato da strumenti di terze parti, che desideri caricare direttamente con l'API tfds, allora questa pagina è per te.

Per caricare i tuoi file .tfrecord devi solo:

  • Segui la convenzione di denominazione TFDS.
  • Aggiungi file di metadati ( dataset_info.json , features.json ) insieme ai file tfrecord.

Limitazioni:

Convenzione di denominazione dei file

TFDS supporta la definizione di un modello per i nomi dei file, che fornisce la flessibilità necessaria per utilizzare diversi schemi di denominazione dei file. Il modello è rappresentato da un tfds.core.ShardedFileTemplate e supporta le seguenti variabili: {DATASET} , {SPLIT} , {FILEFORMAT} , {SHARD_INDEX} , {NUM_SHARDS} e {SHARD_X_OF_Y} . Ad esempio, lo schema di denominazione file predefinito di TFDS è: {DATASET}-{SPLIT}.{FILEFORMAT}-{SHARD_X_OF_Y} . Per MNIST, ciò significa che i nomi dei file avranno il seguente aspetto:

  • mnist-test.tfrecord-00000-of-00001
  • mnist-train.tfrecord-00000-of-00001

Aggiungi metadati

Fornire la struttura delle funzionalità

Affinché TFDS sia in grado di decodificare il protocollo tf.train.Example , devi fornire la struttura tfds.features corrispondente alle tue specifiche. Per esempio:

features = tfds.features.FeaturesDict({
    'image':
        tfds.features.Image(
            shape=(256, 256, 3),
            doc='Picture taken by smartphone, downscaled.'),
    'label':
        tfds.features.ClassLabel(names=['dog', 'cat']),
    'objects':
        tfds.features.Sequence({
            'camera/K': tfds.features.Tensor(shape=(3,), dtype=tf.float32),
        }),
})

Corrisponde alle seguenti specifiche tf.train.Example :

{
    'image': tf.io.FixedLenFeature(shape=(), dtype=tf.string),
    'label': tf.io.FixedLenFeature(shape=(), dtype=tf.int64),
    'objects/camera/K': tf.io.FixedLenSequenceFeature(shape=(3,), dtype=tf.int64),
}

La specifica delle funzionalità consente a TFDS di decodificare automaticamente immagini, video,... Come qualsiasi altro set di dati TFDS, i metadati delle funzionalità (ad esempio nomi di etichette,...) saranno esposti all'utente (ad esempio info.features['label'].names ).

Se controlli la pipeline di generazione

Se generi set di dati al di fuori di TFDS ma controlli comunque la pipeline di generazione, puoi utilizzare tfds.features.FeatureConnector.serialize_example per codificare i tuoi dati da dict[np.ndarray] a tf.train.Example proto bytes :

with tf.io.TFRecordWriter('path/to/file.tfrecord') as writer:
  for ex in all_exs:
    ex_bytes = features.serialize_example(data)
    writer.write(ex_bytes)

Ciò garantirà la compatibilità delle funzionalità con TFDS.

Allo stesso modo, esiste un feature.deserialize_example per decodificare il proto ( esempio )

Se non controlli la pipeline di generazione

Se vuoi vedere come tfds.features sono rappresentati in tf.train.Example , puoi esaminarlo in colab:

Ottieni statistiche sulle divisioni

TFDS richiede di conoscere il numero esatto di esempi all'interno di ciascun frammento. Ciò è richiesto per funzionalità come len(ds) o l' API subplit : split='train[75%:]' .

  • Se disponi di queste informazioni, puoi creare esplicitamente un elenco di tfds.core.SplitInfo e passare alla sezione successiva:

    split_infos = [
        tfds.core.SplitInfo(
            name='train',
            shard_lengths=[1024, ...],  # Num of examples in shard0, shard1,...
            num_bytes=0,  # Total size of your dataset (if unknown, set to 0)
        ),
        tfds.core.SplitInfo(name='test', ...),
    ]
    
  • Se non conosci queste informazioni, puoi calcolarle utilizzando lo script compute_split_info.py (o nel tuo script con tfds.folder_dataset.compute_split_info ). Lancerà una pipeline di raggi che leggerà tutti i frammenti nella directory specificata e calcolerà le informazioni.

Aggiungi file di metadati

Per aggiungere automaticamente i file di metadati corretti al set di dati, utilizza tfds.folder_dataset.write_metadata :

tfds.folder_dataset.write_metadata(
    data_dir='/path/to/my/dataset/1.0.0/',
    features=features,
    # Pass the `out_dir` argument of compute_split_info (see section above)
    # You can also explicitly pass a list of `tfds.core.SplitInfo`.
    split_infos='/path/to/my/dataset/1.0.0/',
    # Pass a custom file name template or use None for the default TFDS
    # file name template.
    filename_template='{SPLIT}-{SHARD_X_OF_Y}.{FILEFORMAT}',

    # Optionally, additional DatasetInfo metadata can be provided
    # See:
    # https://www.tensorflow.org/datasets/api_docs/python/tfds/core/DatasetInfo
    description="""Multi-line description."""
    homepage='http://my-project.org',
    supervised_keys=('image', 'label'),
    citation="""BibTex citation.""",
)

Una volta chiamata la funzione una volta nella directory del set di dati, i file di metadati ( dataset_info.json ,...) sono stati aggiunti e i set di dati sono pronti per essere caricati con TFDS (vedere la sezione successiva).

Carica il set di dati con TFDS

Direttamente dalla cartella

Una volta generati i metadati, i set di dati possono essere caricati utilizzando tfds.builder_from_directory che restituisce un tfds.core.DatasetBuilder con l'API TFDS standard (come tfds.builder ):

builder = tfds.builder_from_directory('~/path/to/my_dataset/3.0.0/')

# Metadata are available as usual
builder.info.splits['train'].num_examples

# Construct the tf.data.Dataset pipeline
ds = builder.as_dataset(split='train[75%:]')
for ex in ds:
  ...

Direttamente da più cartelle

È anche possibile caricare dati da più cartelle. Ciò può accadere, ad esempio, nell'apprendimento per rinforzo quando più agenti generano ciascuno un set di dati separato e si desidera caricarli tutti insieme. Altri casi d'uso sono quando un nuovo set di dati viene prodotto regolarmente, ad esempio un nuovo set di dati al giorno, e si desidera caricare dati da un intervallo di date.

Per caricare dati da più cartelle, utilizzare tfds.builder_from_directories , che restituisce un tfds.core.DatasetBuilder con l'API TFDS standard (come tfds.builder ):

builder = tfds.builder_from_directories(builder_dirs=[
    '~/path/my_dataset/agent1/1.0.0/',
    '~/path/my_dataset/agent2/1.0.0/',
    '~/path/my_dataset/agent3/1.0.0/',
])

# Metadata are available as usual
builder.info.splits['train'].num_examples

# Construct the tf.data.Dataset pipeline
ds = builder.as_dataset(split='train[75%:]')
for ex in ds:
  ...

Struttura delle cartelle (facoltativo)

Per una migliore compatibilità con TFDS, puoi organizzare i tuoi dati come <data_dir>/<dataset_name>[/<dataset_config>]/<dataset_version> . Per esempio:

data_dir/
    dataset0/
        1.0.0/
        1.0.1/
    dataset1/
        config0/
            2.0.0/
        config1/
            2.0.0/

Ciò renderà i tuoi set di dati compatibili con l'API tfds.load / tfds.builder , semplicemente fornendo data_dir/ :

ds0 = tfds.load('dataset0', data_dir='data_dir/')
ds1 = tfds.load('dataset1/config0', data_dir='data_dir/')