نصائح حول الأداء

يوفر هذا المستند تلميحات أداء خاصة بـ TFDS. علما بأن TFDS توفر قواعد البيانات كما tf.data.Dataset الصورة، وبالتالي فإن النصيحة من tf.data دليل لا يزال ساريا.

مجموعات البيانات المعيارية

استخدام tfds.benchmark(ds) لقياس أي tf.data.Dataset الكائن.

تأكد للإشارة إلى batch_size= لتطبيع النتائج (على سبيل المثال 100 ايتر / ثانية -> 3200 السابق / ثانية). يعمل هذا مع أي iterable (على سبيل المثال 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)

مجموعات البيانات الصغيرة (<غيغابايت)

جميع قواعد البيانات TFDS تخزين البيانات على القرص في TFRecord الشكل. لمجموعات البيانات الصغيرة (مثل Mnist، Cifar، ...)، والقراءة من .tfrecord يمكنك إضافة أحمال كبيرة.

نظرًا لاحتواء مجموعات البيانات هذه في الذاكرة ، فمن الممكن تحسين الأداء بشكل كبير عن طريق تخزين مجموعة البيانات مؤقتًا أو تحميلها مسبقًا. لاحظ أن TFDS تقوم تلقائيًا بتخزين مجموعات البيانات الصغيرة مؤقتًا (انظر القسم التالي للحصول على التفاصيل).

تخزين مجموعة البيانات مؤقتًا

فيما يلي مثال على خط أنابيب البيانات الذي يقوم صراحة بتخزين مجموعة البيانات مؤقتًا بعد تسوية الصور.

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)

عند التكرار على مجموعة البيانات هذه ، سيكون التكرار الثاني أسرع بكثير من التكرار الأول بفضل التخزين المؤقت.

التخزين المؤقت التلقائي

بشكل افتراضي ، تقوم TFDS تلقائيًا بتخزين مجموعات البيانات التي تفي بالقيود التالية:

  • تم تحديد الحجم الإجمالي لمجموعة البيانات (جميع الأقسام) و <250 ميغا بايت
  • shuffle_files يتم تعطيل، أو مجرد قشرة واحدة للقراءة

فمن الممكن أن تختار من السيارات التخزين المؤقت عن طريق تمرير try_autocaching=False ل tfds.ReadConfig في tfds.load . ألق نظرة على وثائق كتالوج مجموعة البيانات لمعرفة ما إذا كانت مجموعة بيانات معينة ستستخدم التخزين المؤقت التلقائي.

تحميل البيانات كاملة على هيئة موتر واحد

إذا كانت مجموعة البيانات الخاصة بك تتلاءم مع الذاكرة ، فيمكنك أيضًا تحميل مجموعة البيانات الكاملة كمصفوفة Tensor أو NumPy واحدة. فمن الممكن القيام بذلك عن طريق وضع batch_size=-1 إلى دفعة كل الأمثلة في واحدة tf.Tensor . ثم استخدم tfds.as_numpy للتحويل من tf.Tensor إلى 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,
))

مجموعات البيانات الكبيرة

مجموعات البيانات الكبيرة مجزأة (مقسمة إلى عدة ملفات) ، وعادة لا تتناسب مع الذاكرة ، لذا لا ينبغي تخزينها مؤقتًا.

المراوغة والتدريب

أثناء التدريب ، من المهم خلط البيانات جيدًا ؛ يمكن أن يؤدي خلط البيانات بشكل سيء إلى دقة تدريب أقل.

بالإضافة إلى استخدام ds.shuffle لخلط السجلات، يجب عليك أيضا تعيين shuffle_files=True للحصول على سلوك خلط جيد لمجموعات البيانات الكبيرة التي sharded إلى ملفات متعددة. بخلاف ذلك ، ستقرأ العصور الأجزاء بالترتيب نفسه ، وبالتالي لن تكون البيانات عشوائية حقًا.

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

بالإضافة إلى ذلك، عندما shuffle_files=True ، TFDS تعطيل options.experimental_deterministic ، والتي قد تعطي دفعة أداء طفيف. للحصول على خلط القطعية، فمن الممكن أن الانسحاب من هذه الميزة مع tfds.ReadConfig : إما عن طريق وضع read_config.shuffle_seed أو الكتابة read_config.options.experimental_deterministic .

تقاسم بياناتك تلقائيًا بين العاملين

عندما التدريب على العمال متعددة، يمكنك استخدام input_context حجة tfds.ReadConfig ، لذلك كل عامل سيقرأ مجموعة فرعية من البيانات.

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)

هذا مكمل لواجهة برمجة التطبيقات الفرعية. (لأول مرة يتم تطبيق API subplit train[:50%] وتحويلها إلى قائمة الملفات لقراءة)، ثم ds.shard() يتم تطبيق المرجع على تلك الملفات. على سبيل المثال: عند استخدام train[:50%] مع num_input_pipelines=2 ، كل من عامل 2 سيقرأ 1/4 من البيانات.

عندما shuffle_files=True ، وتعديلا الملفات داخل عامل واحد، ولكن ليس عبر العمال. سيقرأ كل عامل نفس المجموعة الفرعية من الملفات بين العصور.

فك تشفير أسرع للصور

بشكل افتراضي يقوم TFDS بفك تشفير الصور تلقائيًا. ومع ذلك، هناك حالات حيث يمكن أن يكون أكثر performant لللتخطي صورة فك مع tfds.decode.SkipDecoding ويدويا تطبيق tf.io.decode_image المرجع:

  • عند تصفية الأمثلة (مع ds.filter )، لفك الصور بعد أن تم تصفيتها الأمثلة.
  • عندما قص الصور، لاستخدام تنصهر tf.image.decode_and_crop_jpeg المرجع.

رمز لكل من الأمثلة متوفرة في دليل فك شفرة .

تخطي الميزات غير المستخدمة

إذا كنت تستخدم مجموعة فرعية فقط من الميزات ، فمن الممكن تخطي بعض الميزات تمامًا. إذا كانت مجموعة البيانات الخاصة بك تحتوي على العديد من الميزات غير المستخدمة ، فإن عدم فك تشفيرها يمكن أن يؤدي إلى تحسين الأداء بشكل كبير. انظر https://www.tensorflow.org/datasets/decode#only_decode_a_sub-set_of_the_features