เอกสารนี้ให้คำแนะนำด้านประสิทธิภาพเฉพาะชุดข้อมูล TensorFlow (TFDS) โปรดทราบว่า TFDS จัดเตรียมชุดข้อมูลเป็นออบเจ็กต์ tf.data.Dataset
ดังนั้นคำแนะนำจาก คู่มือ tf.data
ยังคงมีผลบังคับใช้
ชุดข้อมูลเกณฑ์มาตรฐาน
ใช้ tfds.benchmark(ds)
เพื่อเปรียบเทียบวัตถุ tf.data.Dataset
ตรวจสอบให้แน่ใจว่าได้ระบุ batch_size=
เพื่อทำให้ผลลัพธ์เป็นมาตรฐาน (เช่น 100 iter/sec -> 3200 ex/sec) ใช้ได้กับ 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)
ชุดข้อมูลขนาดเล็ก (น้อยกว่า 1 GB)
ชุดข้อมูล TFDS ทั้งหมดจัดเก็บข้อมูลบนดิสก์ในรูปแบบ TFRecord
สำหรับชุดข้อมูลขนาดเล็ก (เช่น MNIST, CIFAR-10/-100) การอ่านจาก .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.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 แคชอัตโนมัติ (ด้วย ds.cache()
) ชุดข้อมูลซึ่งเป็นไปตามข้อจำกัดต่อไปนี้:
- ขนาดชุดข้อมูลทั้งหมด (การแบ่งทั้งหมด) ถูกกำหนดและ < 250 MiB
-
shuffle_files
ถูกปิดใช้งาน หรืออ่านเพียงชาร์ดเดียวเท่านั้น
เป็นไปได้ที่จะยกเลิกการแคชอัตโนมัติโดยส่ง try_autocaching=False
ไปที่ tfds.ReadConfig
ใน tfds.load
ดูเอกสารแค็ตตาล็อกชุดข้อมูลเพื่อดูว่าชุดข้อมูลเฉพาะจะใช้แคชอัตโนมัติหรือไม่
กำลังโหลดข้อมูลทั้งหมดเป็น Tensor เดียว
หากชุดข้อมูลของคุณพอดีกับหน่วยความจำ คุณยังสามารถโหลดชุดข้อมูลทั้งหมดเป็นอาร์เรย์ 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
เพื่อให้มีพฤติกรรมการสับเปลี่ยนที่ดีสำหรับชุดข้อมูลขนาดใหญ่ที่แบ่งเป็นหลายไฟล์ มิฉะนั้น ยุคจะอ่านชาร์ดในลำดับเดียวกัน ดังนั้นข้อมูลจะไม่ถูกสุ่มอย่างแท้จริง
ds = tfds.load('imagenet2012', split='train', shuffle_files=True)
นอกจากนี้ เมื่อ shuffle_files=True
, TFDS ปิดใช้งาน options.deterministic
ซึ่งอาจให้ประสิทธิภาพเพิ่มขึ้นเล็กน้อย ในการรับการสับเปลี่ยนแบบกำหนด คุณสามารถเลือกไม่ใช้คุณลักษณะนี้ด้วย tfds.ReadConfig
: โดยการตั้งค่า read_config.shuffle_seed
หรือเขียนทับ read_config.options.deterministic
แบ่งข้อมูลของคุณโดยอัตโนมัติระหว่างผู้ปฏิบัติงาน (TF)
เมื่อฝึกอบรมผู้ปฏิบัติงานหลายคน คุณสามารถใช้อาร์กิวเมนต์ 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)
นี่เป็นส่วนเสริมของ subsplit API ขั้นแรก ใช้ subplit API: train[:50%]
จะถูกแปลงเป็นรายการไฟล์ที่จะอ่าน จากนั้น ds.shard()
op จะถูกนำไปใช้กับไฟล์เหล่านั้น ตัวอย่างเช่น เมื่อใช้ train[:50%]
กับ num_input_pipelines=2
พนักงาน 2 คนแต่ละคนจะอ่านข้อมูล 1/4
เมื่อ shuffle_files=True
ไฟล์จะถูกสับเปลี่ยนภายในผู้ปฏิบัติงานหนึ่งคน แต่ไม่ใช่ข้ามผู้ปฏิบัติงาน ผู้ปฏิบัติงานแต่ละคนจะอ่านชุดย่อยของไฟล์ระหว่างยุคเดียวกัน
แบ่งข้อมูลของคุณโดยอัตโนมัติระหว่างผู้ปฏิบัติงาน (Jax)
ด้วย Jax คุณสามารถใช้ tfds.split_for_jax_process
หรือ tfds.even_splits
API เพื่อกระจายข้อมูลของคุณไปยังผู้ปฏิบัติงาน ดู คู่มือ API แบบแยก ส่วน
split = tfds.split_for_jax_process('train', drop_remainder=True)
ds = tfds.load('my_dataset', split=split)
tfds.split_for_jax_process
เป็นนามแฝงอย่างง่ายสำหรับ:
# 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()]
ถอดรหัสภาพได้เร็วขึ้น
ตามค่าเริ่มต้น TFDS จะถอดรหัสภาพโดยอัตโนมัติ อย่างไรก็ตาม มีบางกรณีที่สามารถข้ามการถอดรหัสภาพด้วย tfds.decode.SkipDecoding
ได้อย่างมีประสิทธิภาพมากกว่า และใช้ tf.io.decode_image
op ด้วยตนเอง:
- เมื่อกรองตัวอย่าง (ด้วย
tf.data.Dataset.filter
) ให้ถอดรหัสรูปภาพหลังจากกรองตัวอย่างแล้ว - เมื่อครอบตัดรูปภาพ ให้ใช้
tf.image.decode_and_crop_jpeg
ที่หลอมรวมเข้าด้วยกัน
รหัสสำหรับทั้งสองตัวอย่างมีอยู่ใน คู่มือการถอดรหัส
ข้ามคุณสมบัติที่ไม่ได้ใช้
หากคุณใช้เพียงส่วนย่อยของคุณลักษณะ คุณสามารถข้ามคุณลักษณะบางอย่างไปโดยสิ้นเชิง หากชุดข้อมูลของคุณมีคุณลักษณะที่ไม่ได้ใช้จำนวนมาก การไม่ถอดรหัสจะช่วยปรับปรุงประสิทธิภาพได้อย่างมาก ดู https://www.tensorflow.org/datasets/decode#only_decode_a_sub-set_of_the_features