Dividir y rebanar

Todos los conjuntos de datos TFDS exponen varias divisiones de datos (por ejemplo 'train' , 'test' ) que se pueden explorar en el catálogo .

Además de las divisiones de conjuntos de datos "oficiales", TFDS permite seleccionar segmentos de divisiones y varias combinaciones.

API de corte

Las instrucciones de división se especifican en tfds.load o tfds.DatasetBuilder.as_dataset a través de split= kwarg.

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

La división puede ser:

  • División simple ( 'train' , 'test' ): Todos los ejemplos dentro de la división seleccionada.
  • Sectores : los sectores tienen la misma semántica que la notación de sector de Python . Las rebanadas pueden ser:
    • Absoluto ( 'train[123:450]' , train[:4000] ): (vea la nota a continuación para la advertencia sobre el orden de lectura)
    • Porcentaje ( 'train[:75%]' , 'train[25%:75%]' ): divide los datos completos en 100 segmentos pares. Si los datos no son divisibles por 100, algún porcentaje podría contener ejemplos adicionales.
    • Fragmento ( tren[: 4fragmento train[:4shard] , train[4shard] ): seleccione todos los ejemplos en el fragmento solicitado. (ver info.splits['train'].num_shards para obtener el número de fragmentos de la división)
  • Unión de divisiones ( 'train+test' , 'train[:25%]+test' ): las divisiones se intercalarán entre sí.
  • Conjunto de datos completo ( 'all' ): 'all' es un nombre de división especial que corresponde a la unión de todas las divisiones (equivalente a 'train+test+...' ).
  • Lista de divisiones ( ['train', 'test'] ): Múltiples tf.data.Dataset se devuelven por separado:
# Returns both train and test split separately
train_ds, test_ds = tfds.load('mnist', split=['train', 'test[:50%]'])

tfds.even_splits y entrenamiento multihost

tfds.even_splits genera una lista de subdivisiones del mismo tamaño que no se superponen.

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

Esto puede ser particularmente útil cuando se entrena en un entorno distribuido, donde cada host debe recibir una porción de los datos originales.

Con Jax , esto se puede simplificar aún más usando 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 es un alias simple para:

# 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 acepta cualquier valor dividido como entrada (por ejemplo 'train[75%:]+test' )

Segmentación y metadatos

Es posible obtener información adicional sobre las divisiones/subdivisiones ( num_examples , file_instructions ,...) utilizando la información del conjunto de datos:

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

Validación cruzada

Ejemplos de validación cruzada de 10 veces usando la API de cadena:

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

Cada uno de los conjuntos de datos de validación será 10%: [0%:10%] , [10%:20%] , ..., [90%:100%] . Y los conjuntos de datos de entrenamiento serán cada uno el 90% complementario: [10%:100%] (para un conjunto de validación correspondiente de [0%:10%] ), `[0%:10%]

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

tfds.core.ReadInstruction y redondeo

En lugar de str , es posible pasar divisiones como tfds.core.ReadInstruction :

Por ejemplo, split = 'train[50%:75%] + test' es equivalente a:

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

unit puede ser:

  • abs : Rebanado absoluto
  • % : Porcentaje de corte
  • shard : corte de fragmento

tfds.ReadInstruction también tiene un argumento de redondeo. Si el número de ejemplos en el conjunto de datos no se divide uniformemente por 100 :

  • rounding='closest' (predeterminado): los ejemplos restantes se distribuyen entre el porcentaje, por lo que algún porcentaje puede contener ejemplos adicionales.
  • rounding='pct1_dropremainder' : Los ejemplos restantes se descartan, pero esto garantiza que todos los porcentajes contienen exactamente el mismo número de ejemplos (p. ej.: len(5%) == 5 * len(1%) ).

Reproducibilidad y determinismo

Durante la generación, para una versión determinada del conjunto de datos, TFDS garantiza que los ejemplos se mezclan de forma determinista en el disco. Entonces, generar el conjunto de datos dos veces (en 2 computadoras diferentes) no cambiará el orden del ejemplo.

De manera similar, la API subdividida siempre seleccionará el mismo set de ejemplos, independientemente de la plataforma, la arquitectura, etc. Esto significa set('train[:20%]') == set('train[:10%]') + set('train[10%:20%]') .

Sin embargo, el orden en que se leen los ejemplos puede no ser determinista. Esto depende de otros parámetros (por ejemplo, si shuffle_files=True ).