TFDS و جبرگرایی

مشاهده در TensorFlow.org در Google Colab اجرا شود در GitHub مشاهده کنید دانلود دفترچه یادداشت

این سند توضیح می دهد:

  • TFDS در مورد جبرگرایی تضمین می کند
  • TFDS نمونه ها را به چه ترتیبی می خواند
  • هشدارها و اخطارهای مختلف

برپایی

مجموعه داده ها

برای درک اینکه TFDS چگونه داده ها را می خواند، زمینه ای لازم است.

در طول نسل، TFDS ارسال داده های اصلی به استاندارد .tfrecord فایل های. برای مجموعه داده های بزرگ، چند .tfrecord فایل ایجاد می کند، هر یک حاوی نمونه های متعدد. ما پاسخ هر .tfrecord تکه های شکسته فایل.

این راهنما از imagenet استفاده می کند که دارای 1024 قطعه است:

import re
import tensorflow_datasets as tfds

imagenet = tfds.builder('imagenet2012')

num_shards = imagenet.info.splits['train'].num_shards
num_examples = imagenet.info.splits['train'].num_examples
print(f'imagenet has {num_shards} shards ({num_examples} examples)')
imagenet has 1024 shards (1281167 examples)

یافتن شناسه نمونه های مجموعه داده

اگر فقط می خواهید در مورد جبرگرایی بدانید، می توانید به بخش زیر بروید.

هر مثال مجموعه داده است منحصر به فرد شناسایی شده توسط id (به عنوان مثال 'imagenet2012-train.tfrecord-01023-of-01024__32' ). شما می توانید این بازیابی id با عبور read_config.add_tfds_id = True که اضافه خواهد شد 'tfds_id' کلیدی در بینی از tf.data.Dataset .

در این آموزش، ما یک ابزار کوچک تعریف می‌کنیم که شناسه‌های نمونه مجموعه داده را چاپ می‌کند (تبدیل به عدد صحیح برای خواندن بیشتر برای انسان):

جبر هنگام خواندن

این بخش تضمین deterministim توضیح می دهد tfds.load .

با shuffle_files=False (پیش فرض)

توسط TFDS به طور پیش فرض مثال عملکرد قطعی ( shuffle_files=False )

# Same as: imagenet.as_dataset(split='train').take(20)
print_ex_ids(imagenet, split='train', take=20)
print_ex_ids(imagenet, split='train', take=20)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1251, 1252, 1253, 1254]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1251, 1252, 1253, 1254]

برای عملکرد، TFDS خرده ریز های متعدد در همان زمان به عنوان خوانده با استفاده از tf.data.Dataset.interleave . ما در این مثال می بینیم که TFDS به سفال 2 تغییر دهید پس از خواندن 16 نمونه ( ..., 14, 15, 1251, 1252, ... ). اطلاعات بیشتر در مورد interleave زیر.

به طور مشابه، subsplit API نیز قطعی است:

print_ex_ids(imagenet, split='train[67%:84%]', take=20)
print_ex_ids(imagenet, split='train[67%:84%]', take=20)
[858382, 858383, 858384, 858385, 858386, 858387, 858388, 858389, 858390, 858391, 858392, 858393, 858394, 858395, 858396, 858397, 859533, 859534, 859535, 859536]
[858382, 858383, 858384, 858385, 858386, 858387, 858388, 858389, 858390, 858391, 858392, 858393, 858394, 858395, 858396, 858397, 859533, 859534, 859535, 859536]

اگر شما آموزش هستید برای بیش از یک دوره، راه اندازی بالا توصیه نمی شود به عنوان تمام دوران را به ذرات در همان جهت به عنوان خوانده شده (بنابراین تصادفی به محدود ds = ds.shuffle(buffer) بافر اندازه).

با shuffle_files=True

با shuffle_files=True ، خرده ریز برای هر دوره حوصلگی، به طوری که خواندن است دیگر قطعی نیست.

print_ex_ids(imagenet, split='train', shuffle_files=True, take=20)
print_ex_ids(imagenet, split='train', shuffle_files=True, take=20)
[568017, 329050, 329051, 329052, 329053, 329054, 329056, 329055, 568019, 568020, 568021, 568022, 568023, 568018, 568025, 568024, 568026, 568028, 568030, 568031]
[43790, 43791, 43792, 43793, 43796, 43794, 43797, 43798, 43795, 43799, 43800, 43801, 43802, 43803, 43804, 43805, 43806, 43807, 43809, 43810]

دستور زیر را ببینید تا به هم زدن فایل قطعی برسید.

اخطار جبر: ارگ ها را در هم بریزند

تغییر read_config.interleave_cycle_length ، read_config.interleave_block_length نظم مثال تغییر خواهد کرد.

TFDS متکی بر tf.data.Dataset.interleave به تنها بار چند تکه در یک بار، بهبود عملکرد و کاهش استفاده از حافظه.

ترتیب مثال فقط برای مقدار ثابتی از آرگهای interleave یکسان است. مشاهده توضیحات میان چیزی به درک آنچه cycle_length و block_length متناظر است.

  • cycle_length=16 ، block_length=16 (به طور پیش فرض، همانند بالا):
print_ex_ids(imagenet, split='train', take=20)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1251, 1252, 1253, 1254]
  • cycle_length=3 ، block_length=2 :
read_config = tfds.ReadConfig(
    interleave_cycle_length=3,
    interleave_block_length=2,
)
print_ex_ids(imagenet, split='train', read_config=read_config, take=20)
[0, 1, 1251, 1252, 2502, 2503, 2, 3, 1253, 1254, 2504, 2505, 4, 5, 1255, 1256, 2506, 2507, 6, 7]

در مثال دوم، ما می بینیم که مجموعه داده 2 (خواندن block_length=2 ) نمونه در یک سفال، و سپس به سفال های بعدی تغییر دهید. هر 2 * 3 ( cycle_length=3 ) مثال ها، آن را به عقب می رود به سفال های اول ( shard0-ex0, shard0-ex1, shard1-ex0, shard1-ex1, shard2-ex0, shard2-ex1, shard0-ex2, shard0-ex3, shard1-ex2, shard1-ex3, shard2-ex2,... ).

تقسیم و سفارش نمونه

هر مثال دارای یک id 0, 1, ..., num_examples-1 . API subsplit را انتخاب کنید یک تکه از نمونه (به عنوان مثال train[:x] را انتخاب کنید 0, 1, ..., x-1 ).

با این حال، در زیر تقسیم، نمونه ها به ترتیب id افزایشی خوانده نمی شوند (به دلیل خرده ها و interleave).

بیشتر به طور خاص، ds.take(x) و split='train[:x]' معادل نیست!

این را می توان به راحتی در مثال میان لایه بالا که در آن نمونه ها از خرده های مختلف آمده اند، مشاهده کرد.

print_ex_ids(imagenet, split='train', take=25)  # tfds.load(..., split='train').take(25)
print_ex_ids(imagenet, split='train[:25]', take=-1)  # tfds.load(..., split='train[:25]')
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]

پس از 16 (block_length) نمونه، .take(25) سوئیچ را به سفال های بعدی در حالی که train[:25] ادامه مطلب نمونه از سفال است.

دستور پخت

به هم زدن فایل قطعی برسید

2 راه برای داشتن درهم ریختگی قطعی وجود دارد:

  1. تنظیم shuffle_seed . توجه: این امر مستلزم تغییر دانه در هر دوره است، در غیر این صورت خرده ها به همان ترتیب بین دوره خوانده می شوند.
read_config = tfds.ReadConfig(
    shuffle_seed=32,
)

# Deterministic order, different from the default shuffle_files=False above
print_ex_ids(imagenet, split='train', shuffle_files=True, read_config=read_config, take=22)
print_ex_ids(imagenet, split='train', shuffle_files=True, read_config=read_config, take=22)
[176411, 176412, 176413, 176414, 176415, 176416, 176417, 176418, 176419, 176420, 176421, 176422, 176423, 176424, 176425, 176426, 710647, 710648, 710649, 710650, 710651, 710652]
[176411, 176412, 176413, 176414, 176415, 176416, 176417, 176418, 176419, 176420, 176421, 176422, 176423, 176424, 176425, 176426, 710647, 710648, 710649, 710650, 710651, 710652]
  1. با استفاده از experimental_interleave_sort_fn : این را می دهد کنترل کامل بر که ذرات به عنوان خوانده شده و در آن سفارش، به جای تکیه بر ds.shuffle سفارش.
def _reverse_order(file_instructions):
  return list(reversed(file_instructions))

read_config = tfds.ReadConfig(
    experimental_interleave_sort_fn=_reverse_order,
)

# Last shard (01023-of-01024) is read first
print_ex_ids(imagenet, split='train', read_config=read_config, take=5)
[1279916, 1279917, 1279918, 1279919, 1279920]

خط لوله قابل پیش‌گیری قطعی را دریافت کنید

این یکی پیچیده تر است. هیچ راه حل آسان و رضایت بخشی وجود ندارد.

  1. بدون ds.shuffle و با زدن قطعی، در تئوری آن را باید ممکن باشد به تعداد نمونه هایی است که خوانده شده است و استنباط که نمونه هایی در داخل در هر ربان خوانده شده است (به عنوان تابعی از cycle_length ، block_length و سفارش سفال). سپس skip ، take برای هر ربان می تواند از طریق تزریق experimental_interleave_sort_fn .

  2. با ds.shuffle این احتمال وجود دارد بدون دوباره پخش خط لوله آموزش کامل غیر ممکن است. این امر نیاز به صرفه جویی در ds.shuffle دولت حائل به استنباط که نمونه هایی خوانده شدهاند. مثالها می تواند غیر مداوم (به عنوان مثال shard5_ex2 ، shard5_ex4 را بخوانند اما shard5_ex3 ).

  3. با ds.shuffle ، یکی از راه خواهد بود به ذخیره تمام shards_ids / example_ids عنوان خوانده شده (استنباط از tfds_id )، سپس استنتاج دستورالعمل فایل را از آن.

ساده ترین مورد برای 1. را داشته است .skip(x).take(y) بازی train[x:x+y] بازی. مستلزم این است:

  • مجموعه cycle_length=1 (تا خرده ریز به ترتیب به عنوان خوانده شده)
  • مجموعه shuffle_files=False
  • استفاده نکنید ds.shuffle

فقط باید در مجموعه داده های عظیمی که آموزش فقط 1 دوره است استفاده شود. نمونه‌ها به ترتیب پیش‌فرض درهم خوانده می‌شوند.

read_config = tfds.ReadConfig(
    interleave_cycle_length=1,  # Read shards sequentially
)

print_ex_ids(imagenet, split='train', read_config=read_config, skip=40, take=22)
# If the job get pre-empted, using the subsplit API will skip at most `len(shard0)`
print_ex_ids(imagenet, split='train[40:]', read_config=read_config, take=22)
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61]
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61]

پیدا کنید کدام خرده/مثال برای یک زیرشاخه داده شده خوانده می شود

با tfds.core.DatasetInfo ، شما باید دسترسی مستقیم به دستورالعمل به عنوان خوانده شده.

imagenet.info.splits['train[44%:45%]'].file_instructions
[FileInstruction(filename='imagenet2012-train.tfrecord-00450-of-01024', skip=700, take=-1, num_examples=551),
 FileInstruction(filename='imagenet2012-train.tfrecord-00451-of-01024', skip=0, take=-1, num_examples=1251),
 FileInstruction(filename='imagenet2012-train.tfrecord-00452-of-01024', skip=0, take=-1, num_examples=1251),
 FileInstruction(filename='imagenet2012-train.tfrecord-00453-of-01024', skip=0, take=-1, num_examples=1251),
 FileInstruction(filename='imagenet2012-train.tfrecord-00454-of-01024', skip=0, take=-1, num_examples=1252),
 FileInstruction(filename='imagenet2012-train.tfrecord-00455-of-01024', skip=0, take=-1, num_examples=1251),
 FileInstruction(filename='imagenet2012-train.tfrecord-00456-of-01024', skip=0, take=-1, num_examples=1251),
 FileInstruction(filename='imagenet2012-train.tfrecord-00457-of-01024', skip=0, take=-1, num_examples=1251),
 FileInstruction(filename='imagenet2012-train.tfrecord-00458-of-01024', skip=0, take=-1, num_examples=1251),
 FileInstruction(filename='imagenet2012-train.tfrecord-00459-of-01024', skip=0, take=-1, num_examples=1251),
 FileInstruction(filename='imagenet2012-train.tfrecord-00460-of-01024', skip=0, take=1001, num_examples=1001)]