عرض على TensorFlow.org | تشغيل في Google Colab | عرض على جيثب | تحميل دفتر |
يوضح هذا المستند:
- تضمن 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
.
في هذا البرنامج التعليمي ، نحدد استخدامًا صغيرًا يطبع أمثلة معرّفات مجموعة البيانات (المحولة بعدد صحيح ليكون أكثر قابلية للقراءة من قبل الإنسان):
def load_dataset(builder, **as_dataset_kwargs):
"""Load the dataset with the tfds_id."""
read_config = as_dataset_kwargs.pop('read_config', tfds.ReadConfig())
read_config.add_tfds_id = True # Set `True` to return the 'tfds_id' key
return builder.as_dataset(read_config=read_config, **as_dataset_kwargs)
def print_ex_ids(
builder,
*,
take: int,
skip: int = None,
**as_dataset_kwargs,
) -> None:
"""Print the example ids from the given dataset split."""
ds = load_dataset(builder, **as_dataset_kwargs)
if skip:
ds = ds.skip(skip)
ds = ds.take(take)
exs = [ex['tfds_id'].numpy().decode('utf-8') for ex in ds]
exs = [id_to_int(tfds_id, builder=builder) for tfds_id in exs]
print(exs)
def id_to_int(tfds_id: str, builder) -> str:
"""Format the tfds_id in a more human-readable."""
match = re.match(r'\w+-(\w+).\w+-(\d+)-of-\d+__(\d+)', tfds_id)
split_name, shard_id, ex_id = match.groups()
split_info = builder.info.splits[split_name]
return sum(split_info.shard_lengths[:int(shard_id)]) + int(ex_id)
الحتمية عند القراءة
يوضح هذا القسم ضمان 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, ...
). المزيد عن تداخل الخوار.
وبالمثل ، فإن واجهة برمجة التطبيقات الفرعية هي أيضًا حتمية:
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 لتحميل سوى بضع شظايا في آن واحد، وتحسين الأداء وتقليل استخدام الذاكرة.
الترتيب النموذجي مضمون فقط ليكون هو نفسه لقيمة ثابتة لرسومات التشذير. انظر وثيقة تعشيق لفهم ما 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,...
).
النظام الفرعي والمثال
كل المثال لديه معرف 0, 1, ..., num_examples-1
. و API subsplit اختيار شريحة من الأمثلة (مثل train[:x]
حدد 0, 1, ..., x-1
).
ومع ذلك ، داخل القسم الفرعي ، لا تتم قراءة الأمثلة بترتيب معرف متزايد (بسبب القطع والتداخل).
وبشكل أكثر تحديدا، 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]
مواصلة القراءة أمثلة من الناحية قشرة الأولى.
وصفات
الحصول على ملف الخلط الحتمية
هناك طريقتان لإجراء خلط حتمي:
- وضع
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]
- باستخدام
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]
احصل على خط أنابيب محدد وقابل للاستباق
هذا أكثر تعقيدا. لا يوجد حل سهل ومرض.
دون
ds.shuffle
ومع خلط حتمية، من الناحية النظرية يجب أن يكون من الممكن الاعتماد على الأمثلة التي تم قراءة ونستنتج التي تم قراءة الأمثلة داخل في كل جزء (بوصفها وظيفة منcycle_length
،block_length
والنظام قشرة). ثمskip
،take
يمكن حقن لكل قشرة من خلالexperimental_interleave_sort_fn
.مع
ds.shuffle
فمن المحتمل المستحيل دون تعيد خط أنابيب التدريب بشكل كامل. فإن ذلك يتطلب توفيرds.shuffle
دولة عازلة لنستنتج التي تم قراءة الأمثلة. أمثلة يمكن أن تكون غير المستمر (على سبيل المثالshard5_ex2
،shard5_ex4
قراءة ولكن ليسshard5_ex3
).مع
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
يجب استخدامه فقط في مجموعة بيانات ضخمة حيث يكون التدريب فترة واحدة فقط. ستتم قراءة الأمثلة بالترتيب العشوائي الافتراضي.
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)]