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:
-
tf.train.SequenceExample
non è supportato, solotf.train.Example
. - Devi essere in grado di esprimere
tf.train.Example
in termini ditfds.features
(vedi sezione seguente).
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:
- Per tradurre
tfds.features
nella struttura leggibile dall'uomo ditf.train.Example
, puoi chiamarefeatures.get_serialized_info()
. - Per ottenere l'esatta specifica
FixedLenFeature
,... passata atf.io.parse_single_example
, puoi utilizzarespec = features.tf_example_spec
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 contfds.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/')