Performans ipuçları

Bu belge, TensorFlow Veri Kümelerine (TFDS) özel performans ipuçları sağlar. TFDS'nin veri kümelerini tf.data.Dataset nesneleri olarak sağladığını, dolayısıyla tf.data kılavuzundaki tavsiyelerin hala geçerli olduğunu unutmayın.

Karşılaştırma veri kümeleri

Herhangi bir tf.data.Dataset nesnesini kıyaslamak için tfds.benchmark(ds) öğesini kullanın.

Sonuçları normalleştirmek için batch_size= değerini belirttiğinizden emin olun (örn. 100 iter/sn -> 3200 ex/sn). Bu, yinelenebilir herhangi bir şeyle çalışır (örn. 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)

Küçük veri kümeleri (1 GB'tan az)

Tüm TFDS veri kümeleri verileri diskte TFRecord formatında saklar. Küçük veri kümeleri için (örn. MNIST, CIFAR-10/-100), .tfrecord okumak önemli miktarda ek yük getirebilir.

Bu veri kümeleri belleğe sığdığından, veri kümesini önbelleğe alarak veya önceden yükleyerek performansı önemli ölçüde artırmak mümkündür. TFDS'nin küçük veri kümelerini otomatik olarak önbelleğe aldığını unutmayın (aşağıdaki bölümde ayrıntılar bulunmaktadır).

Veri kümesini önbelleğe alma

Burada, görüntüleri normalleştirdikten sonra veri kümesini açıkça önbelleğe alan bir veri hattı örneği verilmiştir.

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

Bu veri kümesi üzerinde yineleme yapılırken önbellekleme sayesinde ikinci yineleme birinciye göre çok daha hızlı olacaktır.

Otomatik önbelleğe alma

Varsayılan olarak, TFDS aşağıdaki kısıtlamaları karşılayan veri kümelerini ( ds.cache() ile) otomatik olarak önbelleğe alır:

  • Toplam veri kümesi boyutu (tüm bölümler) tanımlıdır ve < 250 MiB
  • shuffle_files devre dışı bırakıldı veya yalnızca tek bir parça okundu

tfds.load dosyasındaki tfds.ReadConfig dosyasına try_autocaching=False ileterek otomatik önbelleğe almayı devre dışı bırakmak mümkündür. Belirli bir veri kümesinin otomatik önbellek kullanıp kullanmayacağını görmek için veri kümesi kataloğu belgelerine bakın.

Tüm verileri tek bir Tensör olarak yükleme

Veri kümeniz belleğe sığıyorsa veri kümesinin tamamını tek bir Tensor veya NumPy dizisi olarak da yükleyebilirsiniz. Tüm örnekleri tek bir tf.Tensor gruplamak için batch_size=-1 ayarını yaparak bunu yapmak mümkündür. Daha sonra tf.Tensor np.array dönüşüm için tfds.as_numpy kullanın.

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

Büyük veri kümeleri

Büyük veri kümeleri parçalanır (birden fazla dosyaya bölünür) ve genellikle belleğe sığmaz, dolayısıyla önbelleğe alınmamaları gerekir.

Karışıklık ve antrenman

Eğitim sırasında verileri iyi bir şekilde karıştırmak önemlidir; kötü şekilde karıştırılmış veriler, eğitim doğruluğunun düşmesine neden olabilir.

Kayıtları karıştırmak için ds.shuffle kullanmanın yanı sıra, birden fazla dosyaya bölünmüş daha büyük veri kümeleri için iyi karıştırma davranışı elde etmek amacıyla shuffle_files=True de ayarlamanız gerekir. Aksi takdirde dönemler, parçaları aynı sırayla okuyacaktır ve dolayısıyla veriler gerçek anlamda rastgele hale getirilmeyecektir.

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

Ek olarak, shuffle_files=True olduğunda TFDS, options.deterministic devre dışı bırakır ve bu da hafif bir performans artışı sağlayabilir. Belirleyici karıştırma elde etmek için, tfds.ReadConfig ile bu özelliği devre dışı bırakmak mümkündür: ya read_config.shuffle_seed ayarını yaparak ya da read_config.options.deterministic üzerine yazarak.

Verilerinizi çalışanlar arasında otomatik olarak parçalayın (TF)

Birden çok çalışan üzerinde eğitim verirken tfds.ReadConfig öğesinin input_context bağımsız değişkenini kullanabilirsiniz, böylece her çalışan verilerin bir alt kümesini okuyacaktır.

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)

Bu, alt bölme API'sini tamamlayıcı niteliktedir. İlk olarak alt bölme API'si uygulanır: train[:50%] okunacak dosyaların listesine dönüştürülür. Daha sonra bu dosyalara bir ds.shard() işlemi uygulanır. Örneğin, train[:50%] num_input_pipelines=2 ile kullanıldığında, 2 çalışanın her biri verinin 1/4'ünü okuyacaktır.

shuffle_files=True olduğunda, dosyalar bir çalışan içinde karıştırılır ancak çalışanlar arasında karıştırılmaz. Her çalışan dönemler arasında aynı dosya alt kümesini okuyacaktır.

Verilerinizi çalışanlar arasında otomatik olarak parçalayın (Jax)

Jax ile verilerinizi çalışanlar arasında dağıtmak için tfds.split_for_jax_process veya tfds.even_splits API'sini kullanabilirsiniz. Bölünmüş API kılavuzuna bakın.

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

tfds.split_for_jax_process aşağıdakiler için basit bir takma addır:

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

Daha hızlı görüntü kod çözme

Varsayılan olarak TFDS görüntülerin kodunu otomatik olarak çözer. Ancak, tfds.decode.SkipDecoding ile görüntü kod çözme işlemini atlayıp tf.io.decode_image işlemini manuel olarak uygulamanın daha performanslı olabileceği durumlar vardır:

Her iki örneğin kodu kod çözme kılavuzunda mevcuttur.

Kullanılmayan özellikleri atla

Özelliklerin yalnızca bir alt kümesini kullanıyorsanız bazı özellikleri tamamen atlamak mümkündür. Veri kümenizde kullanılmayan birçok özellik varsa bunların kodunu çözmemek performansı önemli ölçüde artırabilir. Bkz. https://www.tensorflow.org/datasets/decode#only_decode_a_sub-set_of_the_features

tf.data tüm RAM'imi kullanıyor!

RAM'iniz sınırlıysa veya tf.data kullanırken çok sayıda veri kümesini paralel olarak yüklüyorsanız, size yardımcı olabilecek birkaç seçenek aşağıda verilmiştir:

Arabellek boyutunu geçersiz kıl

builder.as_dataset(
  read_config=tfds.ReadConfig(
    ...
    override_buffer_size=1024,  # Save quite a bit of RAM.
  ),
  ...
)

Bu, TFRecordDataset (veya eşdeğerine) iletilen buffer_size geçersiz kılar: https://www.tensorflow.org/api_docs/python/tf/data/TFRecordDataset#args

Sihirli davranışları durdurmak için tf.data.Dataset.with_options kullanın

https://www.tensorflow.org/api_docs/python/tf/data/Dataset#with_options

options = tf.data.Options()

# Stop magic stuff that eats up RAM:
options.autotune.enabled = False
options.experimental_distribute.auto_shard_policy = (
  tf.data.experimental.AutoShardPolicy.OFF)
options.experimental_optimization.inject_prefetch = False

data = data.with_options(options)