Załaduj zewnętrzny plik tfrecord za pomocą TFDS

Jeśli masz proto tf.train.Example (wewnątrz .tfrecord , .riegeli ,...), które zostało wygenerowane przez narzędzia stron trzecich i chcesz je bezpośrednio załadować za pomocą API tfds, to ta strona jest dla Ciebie.

Aby załadować pliki .tfrecord , wystarczy:

  • Postępuj zgodnie z konwencją nazewnictwa TFDS.
  • Dodaj pliki metadanych ( dataset_info.json , features.json ) do plików tfrecord.

Ograniczenia:

Konwencja nazewnictwa plików

TFDS obsługuje definiowanie szablonów nazw plików, co zapewnia elastyczność w stosowaniu różnych schematów nazewnictwa plików. Szablon jest reprezentowany przez tfds.core.ShardedFileTemplate i obsługuje następujące zmienne: {DATASET} , {SPLIT} , {FILEFORMAT} , {SHARD_INDEX} , {NUM_SHARDS} i {SHARD_X_OF_Y} . Na przykład domyślny schemat nazewnictwa plików TFDS to: {DATASET}-{SPLIT}.{FILEFORMAT}-{SHARD_X_OF_Y} . W przypadku MNIST oznacza to, że nazwy plików wyglądają następująco:

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

Dodaj metadane

Podaj strukturę funkcji

Aby TFDS mógł zdekodować proto tf.train.Example , musisz podać strukturę tfds.features odpowiadającą Twoim specyfikacjom. Na przykład:

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

Odpowiada następującym specyfikacjom 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),
}

Określenie funkcji umożliwia TFDS automatyczne dekodowanie obrazów, wideo,... Podobnie jak w przypadku innych zbiorów danych TFDS, metadane funkcji (np. nazwy etykiet,...) będą widoczne dla użytkownika (np. info.features['label'].names ).

Jeśli kontrolujesz potok generowania

Jeśli generujesz zestawy danych poza TFDS, ale nadal kontrolujesz potok generowania, możesz użyć tfds.features.FeatureConnector.serialize_example aby zakodować dane z dict[np.ndarray] do 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)

Zapewni to zgodność funkcji z TFDS.

Podobnie istnieje feature.deserialize_example do dekodowania proto ( przykład )

Jeśli nie kontrolujesz potoku generowania

Jeśli chcesz zobaczyć, jak tfds.features są reprezentowane w tf.train.Example , możesz sprawdzić to w Colab:

  • Aby przetłumaczyć tfds.features na czytelną dla człowieka strukturę pliku tf.train.Example , możesz wywołać funkcję features.get_serialized_info() .
  • Aby uzyskać dokładną FixedLenFeature ,... specyfikację przekazaną do tf.io.parse_single_example , możesz użyć spec = features.tf_example_spec

Uzyskaj statystyki dotyczące podziałów

TFDS wymaga znajomości dokładnej liczby przykładów w każdym fragmencie. Jest to wymagane w przypadku funkcji takich jak len(ds) lub API subplit : split='train[75%:]' .

  • Jeśli posiadasz te informacje, możesz jawnie utworzyć listę tfds.core.SplitInfo i przejść do następnej sekcji:

    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', ...),
    ]
    
  • Jeśli nie znasz tych informacji, możesz je obliczyć za pomocą skryptu compute_split_info.py (lub własnego skryptu za pomocą tfds.folder_dataset.compute_split_info ). Uruchomi potok wiązki, który odczyta wszystkie fragmenty w podanym katalogu i obliczy informacje.

Dodaj pliki metadanych

Aby automatycznie dodać odpowiednie pliki metadanych do zbioru danych, użyj 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.""",
)

Po jednorazowym wywołaniu funkcji w katalogu zestawu danych pliki metadanych ( dataset_info.json ,...) zostały dodane i zbiory danych są gotowe do załadowania za pomocą TFDS (patrz następna sekcja).

Załaduj zestaw danych za pomocą TFDS

Bezpośrednio z folderu

Po wygenerowaniu metadanych zestawy danych można załadować za pomocą tfds.builder_from_directory , który zwraca tfds.core.DatasetBuilder ze standardowym API TFDS (np. 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:
  ...

Bezpośrednio z wielu folderów

Możliwe jest także ładowanie danych z wielu folderów. Może się to zdarzyć na przykład podczas uczenia się przez wzmacnianie, gdy wielu agentów generuje oddzielny zestaw danych i chcesz załadować je wszystkie razem. Inne przypadki użycia mają miejsce, gdy regularnie tworzony jest nowy zbiór danych, np. nowy zbiór danych dziennie, a użytkownik chce załadować dane z zakresu dat.

Aby załadować dane z wielu folderów, użyj tfds.builder_from_directories , który zwraca tfds.core.DatasetBuilder ze standardowym API TFDS (jak 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:
  ...

Struktura folderów (opcjonalnie)

Aby uzyskać lepszą kompatybilność z TFDS, możesz uporządkować swoje dane jako <data_dir>/<dataset_name>[/<dataset_config>]/<dataset_version> . Na przykład:

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

Dzięki temu Twoje zbiory danych będą kompatybilne z interfejsem API tfds.load / tfds.builder , po prostu podając data_dir/ :

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