הצג באתר TensorFlow.org | הפעל בגוגל קולאב | הצג ב-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'
מפתח dict מן 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
(ברירת המחדל)
By TFDS מחדל להניב דוגמאות deterministically ( 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, ...
). עוד על השזירה למטה.
באופן דומה, ממשק ה-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)
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 לטעון כמה משברים רק בבת אחת, שיפור הביצועים והפחתת צריכת זיכרון.
מובטח שהסדר לדוגמה יהיה זהה רק עבור ערך קבוע של ארג'ים שזירה. ראה doc 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]
להמשיך לקרוא דוגמאות מן הרסיס הראשון.
מתכונים
קבל עירוב קבצים דטרמיניסטי
ישנן 2 דרכים לערבב דטרמיניסטי:
- הגדרת
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)]