Leistungstipps

Dieses Dokument enthält TFDS-spezifische Leistungstipps. Beachten Sie, dass TFDS Datensätze als böte tf.data.Dataset s, so der Rat von der tf.data Führung gilt nach wie vor.

Benchmark-Datensätze

Verwendung tfds.benchmark(ds) zu jeder Benchmark tf.data.Dataset Objekt.

Achten Sie darauf , die zeigen batch_size= die Ergebnisse zu normalisieren (zB 100 iter / sec -> 3200 ex / sec). Dies funktioniert mit jedem iterable (zB tfds.benchmark(tfds.as_numpy(ds)) ).

ds = tfds.load('mnist', split='train').batch(32).prefetch()
# Display some benchmark statistics
tfds.benchmark(ds, batch_size=32)
# Second iteration is much faster, due to auto-caching
tfds.benchmark(ds, batch_size=32)

Kleine Datensätze (< GB)

Alle TFDS Datensätze speichern die Daten auf der Festplatte im TFRecord Format. Für kleine Datenmengen (zB Mnist, Cifar, ...), aus der Lektüre .tfrecord kann erheblichen Aufwand hinzufügen.

Da diese Datensätze in den Arbeitsspeicher passen, ist es möglich, die Leistung durch Zwischenspeichern oder Vorladen des Datensatzes erheblich zu verbessern. Beachten Sie, dass TFDS kleine Datensätze automatisch zwischenspeichert (siehe nächster Abschnitt für Details).

Caching des Datensatzes

Hier ist ein Beispiel für eine Datenpipeline, die das Dataset nach der Normalisierung der Bilder explizit zwischenspeichert.

def normalize_img(image, label):
  """Normalizes images: `uint8` -> `float32`."""
  return tf.cast(image, tf.float32) / 255., label


ds, ds_info = tfds.load(
    'mnist',
    split='train',
    as_supervised=True,  # returns `(img, label)` instead of dict(image=, ...)
    with_info=True,
)
# Applying normalization before `ds.cache()` to re-use it.
# Note: Random transformations (e.g. images augmentations) should be applied
# after both `ds.cache()` (to avoid caching randomness) and `ds.batch()` (for
# vectorization [1]).
ds = ds.map(normalize_img, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds = ds.cache()
# For true randomness, we set the shuffle buffer to the full dataset size.
ds = ds.shuffle(ds_info.splits['train'].num_examples)
# Batch after shuffling to get unique batches at each epoch.
ds = ds.batch(128)
ds = ds.prefetch(tf.data.experimental.AUTOTUNE)

Beim Durchlaufen dieses Datensatzes ist die zweite Iteration dank des Cachings viel schneller als die erste.

Automatisches Caching

Standardmäßig TFDs Auto-Cache - Speicher (mit ds.cache() ) Datensätzen , die die folgenden Bedingungen erfüllen:

  • Gesamtdatensatzgröße (alle Splits) ist definiert und < 250 MiB
  • shuffle_files ist deaktiviert, oder nur eine einzige Scherbe gelesen

Es ist möglich , von Auto-Caching zu deaktivieren , indem try_autocaching=False zu tfds.ReadConfig in tfds.load . Sehen Sie in der Dokumentation zum Dataset-Katalog nach, ob ein bestimmter Dataset Auto-Cache verwendet.

Laden der vollständigen Daten als einzelner Tensor

Wenn Ihr Dataset in den Speicher passt, können Sie das vollständige Dataset auch als einzelnes Tensor- oder NumPy-Array laden. Es ist möglich , so durch Einstellung zu tun batch_size=-1 zu Charge alle Beispiele in einem einzigen tf.Tensor . Dann nutzen Sie tfds.as_numpy für die Umwandlung von tf.Tensor zu np.array .

(img_train, label_train), (img_test, label_test) = tfds.as_numpy(tfds.load(
    'mnist',
    split=['train', 'test'],
    batch_size=-1,
    as_supervised=True,
))

Große Datensätze

Große Datasets werden fragmentiert (auf mehrere Dateien aufgeteilt) und passen normalerweise nicht in den Arbeitsspeicher, sodass sie nicht zwischengespeichert werden sollten.

Mischen und trainieren

Während des Trainings ist es wichtig, die Daten gut zu mischen; schlecht gemischte Daten können zu einer geringeren Trainingsgenauigkeit führen.

Neben der Verwendung von ds.shuffle Aufzeichnungen zu mischen, sollten Sie auch einstellen shuffle_files=True gutes schlurfendes Verhalten für größere Datensätze zu erhalten , die in mehrere Dateien sharded werden. Andernfalls lesen die Epochen die Shards in derselben Reihenfolge, sodass die Daten nicht wirklich zufällig sind.

ds = tfds.load('imagenet2012', split='train', shuffle_files=True)

Zusätzlich wird , wenn shuffle_files=True , TFDS deaktiviert options.experimental_deterministic , die eine leichte Leistungssteigerung führen kann. Um determinis schlurfenden zu bekommen, ist es möglich, Opt-out dieser Funktion mit tfds.ReadConfig : entweder durch Setzen read_config.shuffle_seed oder Überschreiben read_config.options.experimental_deterministic .

Automatisches Sharing Ihrer Daten zwischen Mitarbeitern (TF)

Beim Training auf mehrere Arbeiter, können Sie das verwenden input_context Argument von tfds.ReadConfig , so dass jeder Arbeiter eine Teilmenge der Daten gelesen werden.

input_context = tf.distribute.InputContext(
    input_pipeline_id=1,  # Worker id
    num_input_pipelines=4,  # Total number of workers
)
read_config = tfds.ReadConfig(
    input_context=input_context,
)
ds = tfds.load('dataset', split='train', read_config=read_config)

Dies ist eine Ergänzung zur Subsplit-API. Zuerst wird die subplit API angewendet ( train[:50%] wird in eine Liste von Dateien umgewandelt zu lesen), dann ein ds.shard() , op ist auf jene Dateien angewendet. Beispiel: Bei der Verwendung der train[:50%] mit num_input_pipelines=2 , wobei jede der 2 Arbeiter wird 1/4 der Daten lesen.

Wenn shuffle_files=True , werden die Dateien innerhalb eines Arbeiters gemischt, aber nicht über Arbeiter. Jeder Arbeiter wird zwischen den Epochen dieselbe Teilmenge von Dateien lesen.

Automatisches Sharding Ihrer Daten für alle Mitarbeiter (Jax)

Mit Jax, können Sie die Verwendung tfds.even_splits API , um Ihre Daten über Arbeitnehmer zu verteilen. Sehen Sie sich die Split - API - Leitfaden .

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

Schnellere Bilddecodierung

Standardmäßig dekodiert TFDS Bilder automatisch. Es gibt jedoch Fälle , in denen es leistungsfähigere sein kann , das Bild zu überspringen , mit Dekodierung tfds.decode.SkipDecoding und manuell die anwenden tf.io.decode_image op:

  • Als Beispiele Filterung (mit ds.filter ), dekodieren Bilder nach den Beispielen gefiltert wurden.
  • Wenn Bilder beschneiden, um das fusionierte zu verwenden tf.image.decode_and_crop_jpeg op.

Der Code für beide Beispiele ist in der zur Verfügung stehenden dekodieren Führung .

Ungenutzte Funktionen überspringen

Wenn Sie nur eine Teilmenge der Funktionen verwenden, können Sie einige Funktionen vollständig überspringen. Wenn Ihr Dataset viele ungenutzte Funktionen enthält, kann deren Nichtdecodierung die Leistung erheblich verbessern. siehe https://www.tensorflow.org/datasets/decode#only_decode_a_sub-set_of_the_features