Dzieli i kroi

Wszystkie zbiory danych TFDS udostępniają różne podziały danych (np. 'train' , 'test' ), które można przeglądać w katalogu . Jako nazwa podziału może zostać użyty dowolny ciąg alfabetyczny, z wyjątkiem all (jest to termin zastrzeżony, który odpowiada sumie wszystkich podziałów, patrz poniżej).

Oprócz „oficjalnych” podziałów zbiorów danych, TFDS umożliwia wybór wycinków podziału i różnych kombinacji.

API krojenia

Instrukcje dzielenia są określone w tfds.load lub tfds.DatasetBuilder.as_dataset poprzez split= kwarg.

ds = tfds.load('my_dataset', split='train[:75%]')
builder = tfds.builder('my_dataset')
ds = builder.as_dataset(split='test+train[:75%]')

Podział może być:

  • Zwykłe nazwy podziału (ciąg taki jak 'train' , 'test' ...): Wszystkie przykłady w wybranym podziale.
  • Plasterki : Plasterki mają taką samą semantykę jak notacja plasterków w Pythonie . Plasterki mogą być:
    • Absolute ( 'train[123:450]' , train[:4000] ): (zobacz uwagę poniżej, aby zapoznać się z zastrzeżeniem dotyczącym kolejności odczytu)
    • Procent ( 'train[:75%]' , 'train[25%:75%]' ): Podziel pełne dane na równe części. Jeśli danych nie można równomiernie podzielić, niektóre procenty mogą zawierać dodatkowe przykłady. Obsługiwane są ułamki procentowe.
    • Shard ( train[:4shard] , train[4shard] ): Wybierz wszystkie przykłady w żądanym fragmencie. (zobacz info.splits['train'].num_shards , aby uzyskać liczbę fragmentów podziału)
  • Suma podziałów ( 'train+test' , 'train[:25%]+test' ): Podziały będą ze sobą przeplatane.
  • Pełny zbiór danych ( 'all' ): 'all' to specjalna nazwa podziału odpowiadająca sumie wszystkich podziałów (równoważna z 'train+test+...' ).
  • Lista podziałów ( ['train', 'test'] ): Wiele tf.data.Dataset jest zwracanych oddzielnie:
# Returns both train and test split separately
train_ds, test_ds = tfds.load('mnist', split=['train', 'test[:50%]'])

tfds.even_splits i szkolenie z wieloma hostami

tfds.even_splits generuje listę nienakładających się na siebie podpodziałów o tym samym rozmiarze.

# Divide the dataset into 3 even parts, each containing 1/3 of the data
split0, split1, split2 = tfds.even_splits('train', n=3)

ds = tfds.load('my_dataset', split=split2)

Może to być szczególnie przydatne podczas uczenia w środowisku rozproszonym, gdzie każdy host powinien otrzymać wycinek oryginalnych danych.

W Jax można to jeszcze bardziej uprościć, używając tfds.split_for_jax_process :

split = tfds.split_for_jax_process('train', drop_remainder=True)
ds = tfds.load('my_dataset', split=split)

tfds.split_for_jax_process to prosty alias dla:

# The current `process_index` loads only `1 / process_count` of the data.
splits = tfds.even_splits('train', n=jax.process_count(), drop_remainder=True)
split = splits[jax.process_index()]

tfds.even_splits , tfds.split_for_jax_process akceptuje dowolną podzieloną wartość jako dane wejściowe (np 'train[75%:]+test' )

Krojenie i metadane

Możliwe jest uzyskanie dodatkowych informacji na temat podziałów/podpodziałów ( num_examples , file_instructions ,...) przy użyciu informacji o zestawie danych :

builder = tfds.builder('my_dataset')
builder.info.splits['train'].num_examples  # 10_000
builder.info.splits['train[:75%]'].num_examples  # 7_500 (also works with slices)
builder.info.splits.keys()  # ['train', 'test']

Walidacja krzyżowa

Przykłady 10-krotnej walidacji krzyżowej przy użyciu interfejsu API string:

vals_ds = tfds.load('mnist', split=[
    f'train[{k}%:{k+10}%]' for k in range(0, 100, 10)
])
trains_ds = tfds.load('mnist', split=[
    f'train[:{k}%]+train[{k+10}%:]' for k in range(0, 100, 10)
])

Każdy zestaw danych walidacyjnych będzie wynosił 10%: [0%:10%] , [10%:20%] , ..., [90%:100%] . Każdy zestaw danych szkoleniowych będzie komplementarnym 90%: [10%:100%] (dla odpowiedniego zestawu walidacyjnego wynoszącego [0%:10%] ), `[0%:10%]

  • [20%:100%] (for a validation set of [10%:20%]`),...

tfds.core.ReadInstruction i zaokrąglanie

Zamiast str można przekazać podziały w formie tfds.core.ReadInstruction :

Na przykład split = 'train[50%:75%] + test' jest równoważny:

split = (
    tfds.core.ReadInstruction(
        'train',
        from_=50,
        to=75,
        unit='%',
    )
    + tfds.core.ReadInstruction('test')
)
ds = tfds.load('my_dataset', split=split)

unit może być:

  • abs : Absolutne krojenie
  • % : Procent krojenia
  • shard : Krojenie odłamka

tfds.ReadInstruction ma również argument zaokrąglania. Jeśli liczba przykładów w zbiorze danych nie jest podzielona równo:

  • rounding='closest' (domyślnie): pozostałe przykłady są rozdzielane pomiędzy procenty, więc niektóre procenty mogą zawierać dodatkowe przykłady.
  • rounding='pct1_dropremainder' : Pozostałe przykłady są pomijane, ale gwarantuje to, że wszystkie procenty zawierają dokładnie tę samą liczbę przykładów (np.: len(5%) == 5 * len(1%) ).

Powtarzalność i determinizm

Podczas generowania, dla danej wersji zbioru danych, TFDS gwarantuje, że przykłady zostaną deterministycznie przetasowane na dysku. Zatem dwukrotne wygenerowanie zestawu danych (na 2 różnych komputerach) nie zmieni przykładowej kolejności.

Podobnie subsplit API zawsze wybierze ten sam set przykładów, niezależnie od platformy, architektury itp. Oznacza to set('train[:20%]') == set('train[:10%]') + set('train[10%:20%]') .

Jednakże kolejność odczytywania przykładów może nie być deterministyczna. Zależy to od innych parametrów (np. czy shuffle_files=True ).