Сплит и нарезка

Все наборы данных TFDS предоставляют различные разделения данных (например, 'train' , 'test' ), которые можно изучить в каталоге . В качестве имени разделения может использоваться любая алфавитная строка, кроме all (это зарезервированный термин, соответствующий объединению всех разделений, см. ниже).

Помимо «официальных» разбиений набора данных, TFDS позволяет выбирать срезы разбиений и различные комбинации.

API нарезки

Инструкции по срезу указываются в tfds.load или tfds.DatasetBuilder.as_dataset через параметр split= kwarg.

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

Разделение может быть:

  • Простые имена разделений (например, 'train' , 'test' , ...): все примеры внутри выбранного разделения.
  • Срезы : Срезы имеют ту же семантику, что и нотация срезов Python . Срезы могут быть:
    • Абсолют ( 'train[123:450]' , train[:4000] ): (предупреждение о порядке чтения см. в примечании ниже)
    • Процент ( 'train[:75%]' , 'train[25%:75%]' ): разделите полные данные на четные фрагменты. Если данные не делятся без остатка, некоторые проценты могут содержать дополнительные примеры. Поддерживаются дробные проценты.
    • Осколок ( train[:4shard] , train[4shard] ): выберите все примеры в запрошенном сегменте. (см. info.splits['train'].num_shards чтобы узнать количество фрагментов разделения)
  • Объединение разбиений ( 'train+test' , 'train[:25%]+test' ): разбиения будут чередоваться вместе.
  • Полный набор данных ( 'all' ): 'all' — это специальное имя разделения, соответствующее объединению всех разделений (эквивалентно 'train+test+...' ).
  • Список разделений ( ['train', 'test'] ): несколько tf.data.Dataset возвращаются отдельно:
# Returns both train and test split separately
train_ds, test_ds = tfds.load('mnist', split=['train', 'test[:50%]'])

tfds.even_splits и обучение на нескольких хостах

tfds.even_splits генерирует список непересекающихся подразделов одинакового размера.

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

Это может быть особенно полезно при обучении в распределенной среде, где каждый хост должен получать часть исходных данных.

С Jax это можно еще больше упростить, используя 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 — это простой псевдоним для:

# 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 принимает любое значение разделения в качестве входных данных (например 'train[75%:]+test' )

Нарезка и метаданные

Можно получить дополнительную информацию о разделениях/подразделениях ( num_examples , file_instructions ,...), используя информацию о наборе данных :

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']

Перекрестная проверка

Примеры 10-кратной перекрестной проверки с использованием строкового API:

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

Каждый набор данных проверки будет равен 10%: [0%:10%] , [10%:20%] , ..., [90%:100%] . И каждый набор обучающих данных будет дополнять друг друга 90%: [10%:100%] (для соответствующего набора проверки [0%:10%] ), `[0%:10%]

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

tfds.core.ReadInstruction и округление

Вместо str можно передавать разделения как tfds.core.ReadInstruction :

Например, split = 'train[50%:75%] + test' эквивалентно:

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

unit может быть:

  • abs : Абсолютная нарезка
  • % : Процентное разделение
  • shard : нарезка осколков

tfds.ReadInstruction также имеет аргумент округления. Если количество примеров в наборе данных не делится поровну:

  • rounding='closest' (по умолчанию): оставшиеся примеры распределены по процентам, поэтому некоторые проценты могут содержать дополнительные примеры.
  • rounding='pct1_dropremainder' : Остальные примеры отбрасываются, но это гарантирует, что все проценты будут содержать одинаковое количество примеров (например: len(5%) == 5 * len(1%) .

Воспроизводимость и детерминизм

Во время генерации для данной версии набора данных TFDS гарантирует, что примеры детерминированно перемешиваются на диске. Таким образом, генерация набора данных дважды (на двух разных компьютерах) не изменит порядок примеров.

Аналогично, API подразделения всегда будет выбирать один и тот же set примеров, независимо от платформы, архитектуры и т. д. Это означает set('train[:20%]') == set('train[:10%]') + set('train[10%:20%]') .

Однако порядок чтения примеров может быть недетерминированным . Это зависит от других параметров (например, от того, shuffle_files=True ).