ดูบน TensorFlow.org | ทำงานใน Google Colab | ดูแหล่งที่มาบน GitHub | ดาวน์โหลดโน๊ตบุ๊ค |
ภาพรวม
บทช่วยสอนนี้สาธิตการเสริมข้อมูล: เทคนิคในการเพิ่มความหลากหลายของชุดการฝึกของคุณโดยใช้การแปลงแบบสุ่ม (แต่เหมือนจริง) เช่น การหมุนภาพ
คุณจะได้เรียนรู้วิธีใช้การเพิ่มข้อมูลในสองวิธี:
- ใช้เลเยอร์การประมวลผลล่วงหน้าของ Keras เช่น
tf.keras.layers.Resizing
,tf.keras.layers.Rescaling
,tf.keras.layers.RandomFlip
และtf.keras.layers.RandomRotation
- ใช้
tf.image
เช่นtf.image.flip_left_right
,tf.image.rgb_to_grayscale
,tf.image.adjust_brightness
,tf.image.central_crop
และtf.image.stateless_random*
ติดตั้ง
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds
from tensorflow.keras import layers
ดาวน์โหลดชุดข้อมูล
บทช่วยสอนนี้ใช้ชุดข้อมูล tf_flowers เพื่อความสะดวก ให้ดาวน์โหลดชุดข้อมูลโดยใช้ TensorFlow Datasets หากคุณต้องการเรียนรู้เกี่ยวกับวิธีการอื่นๆ ในการนำเข้าข้อมูล โปรดดูบทแนะนำการ โหลดรูปภาพ
(train_ds, val_ds, test_ds), metadata = tfds.load(
'tf_flowers',
split=['train[:80%]', 'train[80%:90%]', 'train[90%:]'],
with_info=True,
as_supervised=True,
)
ชุดข้อมูลดอกไม้มีห้าคลาส
num_classes = metadata.features['label'].num_classes
print(num_classes)
5
มาดึงรูปภาพจากชุดข้อมูลและใช้เพื่อสาธิตการเพิ่มข้อมูล
get_label_name = metadata.features['label'].int2str
image, label = next(iter(train_ds))
_ = plt.imshow(image)
_ = plt.title(get_label_name(label))
2022-01-26 05:09:18.712477: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
ใช้เลเยอร์การประมวลผลล่วงหน้าของ Keras
การปรับขนาดและการปรับขนาด
คุณสามารถใช้เลเยอร์การประมวลผลล่วงหน้าของ Keras เพื่อปรับขนาดรูปภาพของคุณให้เป็นรูปร่างที่สอดคล้องกัน (ด้วย tf.keras.layers.Resizing
) และเพื่อปรับขนาดค่าพิกเซลใหม่ (ด้วย tf.keras.layers.Rescaling
)
IMG_SIZE = 180
resize_and_rescale = tf.keras.Sequential([
layers.Resizing(IMG_SIZE, IMG_SIZE),
layers.Rescaling(1./255)
])
คุณสามารถเห็นภาพผลลัพธ์ของการใช้เลเยอร์เหล่านี้กับรูปภาพ
result = resize_and_rescale(image)
_ = plt.imshow(result)
ตรวจสอบว่าพิกเซลอยู่ในช่วง [0, 1]
:
print("Min and max pixel values:", result.numpy().min(), result.numpy().max())
Min and max pixel values: 0.0 1.0
การเสริมข้อมูล
คุณสามารถใช้เลเยอร์การประมวลผลล่วงหน้าของ Keras สำหรับการเพิ่มข้อมูลได้เช่นกัน เช่น tf.keras.layers.RandomFlip
และ tf.keras.layers.RandomRotation
มาสร้างเลเยอร์การประมวลผลล่วงหน้าสองสามเลเยอร์แล้วนำไปใช้กับรูปภาพเดียวกันซ้ำๆ
data_augmentation = tf.keras.Sequential([
layers.RandomFlip("horizontal_and_vertical"),
layers.RandomRotation(0.2),
])
# Add the image to a batch.
image = tf.expand_dims(image, 0)
plt.figure(figsize=(10, 10))
for i in range(9):
augmented_image = data_augmentation(image)
ax = plt.subplot(3, 3, i + 1)
plt.imshow(augmented_image[0])
plt.axis("off")
WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
มีเลเยอร์การประมวลผลล่วงหน้ามากมายที่คุณสามารถใช้สำหรับการเพิ่มข้อมูลได้ ซึ่งรวมถึง tf.keras.layers.RandomContrast
, tf.keras.layers.RandomCrop
, tf.keras.layers.RandomZoom
และอื่นๆ
สองตัวเลือกในการใช้เลเยอร์การประมวลผลล่วงหน้าของ Keras
คุณสามารถใช้เลเยอร์การประมวลผลล่วงหน้าเหล่านี้ได้สองวิธี โดยมีข้อดีข้อเสีย
ตัวเลือกที่ 1: ทำให้เลเยอร์ก่อนการประมวลผลเป็นส่วนหนึ่งของโมเดลของคุณ
model = tf.keras.Sequential([
# Add the preprocessing layers you created earlier.
resize_and_rescale,
data_augmentation,
layers.Conv2D(16, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
# Rest of your model.
])
มีสองประเด็นสำคัญที่ควรทราบในกรณีนี้:
การเพิ่มข้อมูลจะทำงานบนอุปกรณ์ ซิงโครนัสกับเลเยอร์ที่เหลือของคุณ และได้รับประโยชน์จากการเร่งความเร็วของ GPU
เมื่อคุณส่งออกแบบจำลองของคุณโดยใช้
model.save
เลเยอร์การประมวลผลล่วงหน้าจะถูกบันทึกพร้อมกับส่วนที่เหลือของแบบจำลองของคุณ หากคุณปรับใช้โมเดลนี้ในภายหลัง โมเดลจะสร้างมาตรฐานให้กับรูปภาพโดยอัตโนมัติ (ตามการกำหนดค่าเลเยอร์ของคุณ) วิธีนี้ช่วยให้คุณไม่ต้องพยายามปรับใช้ลอจิกฝั่งเซิร์ฟเวอร์อีกครั้ง
ตัวเลือกที่ 2: ใช้เลเยอร์การประมวลผลล่วงหน้ากับชุดข้อมูลของคุณ
aug_ds = train_ds.map(
lambda x, y: (resize_and_rescale(x, training=True), y))
ด้วยวิธีการนี้ คุณใช้ Dataset.map
เพื่อสร้างชุดข้อมูลที่ให้ชุดของรูปภาพเสริม ในกรณีนี้:
- การเพิ่มข้อมูลจะเกิดขึ้นแบบอะซิงโครนัสบน CPU และไม่มีการบล็อก คุณสามารถทับซ้อนการฝึกโมเดลของคุณบน GPU ด้วยการประมวลผลข้อมูลล่วงหน้า โดยใช้
Dataset.prefetch
ที่แสดงด้านล่าง - ในกรณีนี้ เลเยอร์การประมวลผลล่วงหน้าจะไม่ถูกส่งออกพร้อมกับโมเดลเมื่อคุณเรียกใช้
Model.save
คุณจะต้องแนบไฟล์เหล่านี้กับโมเดลของคุณก่อนที่จะบันทึกหรือปรับใช้ใหม่ทางฝั่งเซิร์ฟเวอร์ หลังการฝึก คุณสามารถแนบเลเยอร์การประมวลผลล่วงหน้าก่อนส่งออกได้
คุณสามารถดูตัวอย่างตัวเลือกแรกได้ในบทแนะนำการ จัดหมวดหมู่รูปภาพ มาสาธิตตัวเลือกที่สองกันที่นี่
ใช้เลเยอร์การประมวลผลล่วงหน้ากับชุดข้อมูล
กำหนดค่าการฝึกอบรม การตรวจสอบ และทดสอบชุดข้อมูลด้วยเลเยอร์การประมวลผลล่วงหน้าของ Keras ที่คุณสร้างไว้ก่อนหน้านี้ คุณยังกำหนดค่าชุดข้อมูลสำหรับประสิทธิภาพ โดยใช้การอ่านแบบขนานและการดึงข้อมูลล่วงหน้าแบบบัฟเฟอร์เพื่อให้แบตช์จากดิสก์ที่ไม่มี I/O กลายเป็นการบล็อก (เรียนรู้เพิ่มเติมเกี่ยวกับประสิทธิภาพของชุดข้อมูลใน ประสิทธิภาพที่ ดีขึ้น ด้วยคู่มือ tf.data API )
batch_size = 32
AUTOTUNE = tf.data.AUTOTUNE
def prepare(ds, shuffle=False, augment=False):
# Resize and rescale all datasets.
ds = ds.map(lambda x, y: (resize_and_rescale(x), y),
num_parallel_calls=AUTOTUNE)
if shuffle:
ds = ds.shuffle(1000)
# Batch all datasets.
ds = ds.batch(batch_size)
# Use data augmentation only on the training set.
if augment:
ds = ds.map(lambda x, y: (data_augmentation(x, training=True), y),
num_parallel_calls=AUTOTUNE)
# Use buffered prefetching on all datasets.
return ds.prefetch(buffer_size=AUTOTUNE)
train_ds = prepare(train_ds, shuffle=True, augment=True)
val_ds = prepare(val_ds)
test_ds = prepare(test_ds)
ฝึกนางแบบ
เพื่อความสมบูรณ์ ตอนนี้คุณจะต้องฝึกแบบจำลองโดยใช้ชุดข้อมูลที่คุณเพิ่งจัดเตรียม
โมเดล Sequential ประกอบด้วยบล็อกการบิดสามบล็อก ( tf.keras.layers.Conv2D
) ที่มีเลเยอร์การรวมสูงสุด ( tf.keras.layers.MaxPooling2D
) ในแต่ละอัน มีเลเยอร์ที่เชื่อมต่ออย่างสมบูรณ์ ( tf.keras.layers.Dense
) โดยมี 128 ยูนิตอยู่ด้านบนซึ่งเปิดใช้งานโดยฟังก์ชันการเปิดใช้งาน ReLU ( 'relu'
) โมเดลนี้ไม่ได้รับการปรับแต่งเพื่อความแม่นยำ (เป้าหมายคือเพื่อแสดงกลไกให้คุณเห็น)
model = tf.keras.Sequential([
layers.Conv2D(16, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(32, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(64, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dense(num_classes)
])
เลือก tf.keras.optimizers.Adam
Optimizer และ tf.keras.losses.SparseCategoricalCrossentropy
loss function ในการดูการฝึกอบรมและการตรวจสอบความถูกต้องสำหรับช่วงการฝึกแต่ละครั้ง ให้ส่งอาร์กิวเมนต์ metrics
ไปที่ Model.compile
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
ฝึกสองสามยุค:
epochs=5
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs
)
Epoch 1/5 92/92 [==============================] - 13s 110ms/step - loss: 1.2768 - accuracy: 0.4622 - val_loss: 1.0929 - val_accuracy: 0.5640 Epoch 2/5 92/92 [==============================] - 3s 25ms/step - loss: 1.0579 - accuracy: 0.5749 - val_loss: 0.9711 - val_accuracy: 0.6349 Epoch 3/5 92/92 [==============================] - 3s 26ms/step - loss: 0.9677 - accuracy: 0.6291 - val_loss: 0.9764 - val_accuracy: 0.6431 Epoch 4/5 92/92 [==============================] - 3s 25ms/step - loss: 0.9150 - accuracy: 0.6468 - val_loss: 0.8906 - val_accuracy: 0.6431 Epoch 5/5 92/92 [==============================] - 3s 25ms/step - loss: 0.8636 - accuracy: 0.6604 - val_loss: 0.8233 - val_accuracy: 0.6730
loss, acc = model.evaluate(test_ds)
print("Accuracy", acc)
12/12 [==============================] - 5s 14ms/step - loss: 0.7922 - accuracy: 0.6948 Accuracy 0.6948229074478149
การเพิ่มข้อมูลที่กำหนดเอง
คุณยังสามารถสร้างเลเยอร์การเพิ่มข้อมูลที่กำหนดเองได้อีกด้วย
บทช่วยสอนส่วนนี้แสดงวิธีดำเนินการสองวิธี:
- ขั้นแรก คุณจะต้องสร้างเลเยอร์
tf.keras.layers.Lambda
นี่เป็นวิธีที่ดีในการเขียนโค้ดที่กระชับ - ถัดไป คุณจะเขียนเลเยอร์ใหม่ผ่าน คลาสย่อย ซึ่งช่วยให้คุณควบคุมได้มากขึ้น
เลเยอร์ทั้งสองจะสุ่มสลับสีในภาพตามความน่าจะเป็น
def random_invert_img(x, p=0.5):
if tf.random.uniform([]) < p:
x = (255-x)
else:
x
return x
def random_invert(factor=0.5):
return layers.Lambda(lambda x: random_invert_img(x, factor))
random_invert = random_invert()
plt.figure(figsize=(10, 10))
for i in range(9):
augmented_image = random_invert(image)
ax = plt.subplot(3, 3, i + 1)
plt.imshow(augmented_image[0].numpy().astype("uint8"))
plt.axis("off")
2022-01-26 05:09:53.045204: W tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/gpu_backend_lib.cc:399] target triple not found in the module 2022-01-26 05:09:53.045264: W tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/gpu_backend_lib.cc:399] target triple not found in the module 2022-01-26 05:09:53.045312: W tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/gpu_backend_lib.cc:399] target triple not found in the module 2022-01-26 05:09:53.045369: W tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/gpu_backend_lib.cc:399] target triple not found in the module 2022-01-26 05:09:53.045418: W tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/gpu_backend_lib.cc:399] target triple not found in the module 2022-01-26 05:09:53.045467: W tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/gpu_backend_lib.cc:399] target triple not found in the module 2022-01-26 05:09:53.045511: W tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/gpu_backend_lib.cc:399] target triple not found in the module 2022-01-26 05:09:53.047630: W tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/gpu_backend_lib.cc:399] target triple not found in the module
ถัดไป ใช้เลเยอร์ที่กำหนดเองโดยการจัด คลาสย่อย :
class RandomInvert(layers.Layer):
def __init__(self, factor=0.5, **kwargs):
super().__init__(**kwargs)
self.factor = factor
def call(self, x):
return random_invert_img(x)
_ = plt.imshow(RandomInvert()(image)[0])
เลเยอร์ทั้งสองนี้สามารถใช้ได้ตามที่อธิบายไว้ในตัวเลือกที่ 1 และ 2 ด้านบน
ใช้ tf.image
ยูทิลิตี้การประมวลผลล่วงหน้าของ Keras ด้านบนนั้นสะดวก แต่สำหรับการควบคุมที่ละเอียดยิ่งขึ้น คุณสามารถเขียนไปป์ไลน์หรือเลเยอร์การเสริมข้อมูลของคุณเองโดยใช้ tf.data
และ tf.image
(คุณอาจต้องการตรวจสอบ TensorFlow Addons Image: Operations และ TensorFlow I/O: Color Space Conversions )
เนื่องจากก่อนหน้านี้ชุดข้อมูลดอกไม้ได้รับการกำหนดค่าด้วยการเพิ่มข้อมูล ให้นำเข้าใหม่เพื่อเริ่มต้นใหม่:
(train_ds, val_ds, test_ds), metadata = tfds.load(
'tf_flowers',
split=['train[:80%]', 'train[80%:90%]', 'train[90%:]'],
with_info=True,
as_supervised=True,
)
ดึงภาพที่จะทำงานกับ:
image, label = next(iter(train_ds))
_ = plt.imshow(image)
_ = plt.title(get_label_name(label))
2022-01-26 05:09:59.918847: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.ตัวยึดตำแหน่ง33
ลองใช้ฟังก์ชันต่อไปนี้ในการแสดงภาพและเปรียบเทียบภาพต้นฉบับและภาพเสริมกัน:
def visualize(original, augmented):
fig = plt.figure()
plt.subplot(1,2,1)
plt.title('Original image')
plt.imshow(original)
plt.subplot(1,2,2)
plt.title('Augmented image')
plt.imshow(augmented)
การเสริมข้อมูล
พลิกภาพ
พลิกรูปภาพในแนวตั้งหรือแนวนอนด้วย tf.image.flip_left_right
:
flipped = tf.image.flip_left_right(image)
visualize(image, flipped)
ภาพสีเทา
คุณสามารถสเกลภาพสีเทาด้วย tf.image.rgb_to_grayscale
:
grayscaled = tf.image.rgb_to_grayscale(image)
visualize(image, tf.squeeze(grayscaled))
_ = plt.colorbar()
อิ่มตัวภาพ
ทำให้ภาพอิ่มตัวด้วย tf.image.adjust_saturation
โดยระบุปัจจัยความอิ่มตัว:
saturated = tf.image.adjust_saturation(image, 3)
visualize(image, saturated)
เปลี่ยนความสว่างของภาพ
เปลี่ยนความสว่างของภาพด้วย tf.image.adjust_brightness
โดยระบุปัจจัยความสว่าง:
bright = tf.image.adjust_brightness(image, 0.4)
visualize(image, bright)
ครอบตัดรูปภาพตรงกลาง
ครอบตัดรูปภาพจากกึ่งกลางไปยังส่วนรูปภาพที่คุณต้องการโดยใช้ tf.image.central_crop
:
cropped = tf.image.central_crop(image, central_fraction=0.5)
visualize(image, cropped)
หมุนภาพ
หมุนรูปภาพ 90 องศาด้วย tf.image.rot90
:
rotated = tf.image.rot90(image)
visualize(image, rotated)
การแปลงแบบสุ่ม
การใช้การแปลงแบบสุ่มกับรูปภาพสามารถช่วยทำให้ภาพรวมและขยายชุดข้อมูลได้กว้างขึ้น tf.image
API ปัจจุบันมีการดำเนินการรูปภาพแบบสุ่มแปดแบบ (ops):
-
tf.image.stateless_random_brightness
-
tf.image.stateless_random_contrast
-
tf.image.stateless_random_crop
-
tf.image.stateless_random_flip_left_right
-
tf.image.stateless_random_flip_up_down
-
tf.image.stateless_random_hue
-
tf.image.stateless_random_jpeg_quality
-
tf.image.stateless_random_saturation
ops ภาพสุ่มเหล่านี้ทำงานได้อย่างหมดจด: เอาต์พุตขึ้นอยู่กับอินพุตเท่านั้น ซึ่งทำให้ง่ายต่อการใช้งานในไพพ์ไลน์อินพุตที่มีประสิทธิภาพสูงและกำหนดได้ พวกเขาต้องการค่า seed
ที่จะป้อนในแต่ละขั้นตอน ให้ seed
เดียวกัน ส่งคืนผลลัพธ์เดียวกันโดยไม่ขึ้นกับจำนวนครั้งที่ถูกเรียก
ในส่วนต่อไปนี้ คุณจะ:
- ดูตัวอย่างการใช้การดำเนินการรูปภาพแบบสุ่มเพื่อแปลงรูปภาพ
- สาธิตวิธีการใช้การแปลงแบบสุ่มกับชุดข้อมูลการฝึกอบรม
สุ่มเปลี่ยนความสว่างของภาพ
สุ่มเปลี่ยนความสว่างของ image
โดยใช้ tf.image.stateless_random_brightness
โดยให้ปัจจัยความสว่างและ seed
ปัจจัยความสว่างจะถูกเลือกแบบสุ่มในช่วง [-max_delta, max_delta)
และสัมพันธ์กับ seed
ที่กำหนด
for i in range(3):
seed = (i, 0) # tuple of size (2,)
stateless_random_brightness = tf.image.stateless_random_brightness(
image, max_delta=0.95, seed=seed)
visualize(image, stateless_random_brightness)
สุ่มเปลี่ยนความคมชัดของภาพ
สุ่มเปลี่ยนความคมชัดของ image
โดยใช้ tf.image.stateless_random_contrast
โดยให้ช่วงความคมชัดและ seed
ช่วงความคมชัดจะถูกเลือกแบบสุ่มในช่วงเวลา [lower, upper]
และสัมพันธ์กับ seed
ที่กำหนด
for i in range(3):
seed = (i, 0) # tuple of size (2,)
stateless_random_contrast = tf.image.stateless_random_contrast(
image, lower=0.1, upper=0.9, seed=seed)
visualize(image, stateless_random_contrast)
ครอบตัดรูปภาพแบบสุ่ม
ครอบตัด image
แบบสุ่มโดยใช้ tf.image.stateless_random_crop
โดยระบุ size
เป้าหมายและ seed
ส่วนที่ถูกครอบตัดออกจาก image
จะอยู่ที่ออฟเซ็ตที่เลือกแบบสุ่มและสัมพันธ์กับ seed
ที่กำหนด
for i in range(3):
seed = (i, 0) # tuple of size (2,)
stateless_random_crop = tf.image.stateless_random_crop(
image, size=[210, 300, 3], seed=seed)
visualize(image, stateless_random_crop)
ใช้การเสริมกับชุดข้อมูล
เรามาดาวน์โหลดชุดข้อมูลภาพกันก่อนอีกครั้งในกรณีที่มีการแก้ไขในส่วนก่อนหน้า
(train_datasets, val_ds, test_ds), metadata = tfds.load(
'tf_flowers',
split=['train[:80%]', 'train[80%:90%]', 'train[90%:]'],
with_info=True,
as_supervised=True,
)
ถัดไป กำหนดฟังก์ชันยูทิลิตี้สำหรับการปรับขนาดและปรับขนาดรูปภาพ ฟังก์ชันนี้จะใช้ในการรวมขนาดและขนาดของรูปภาพในชุดข้อมูล:
def resize_and_rescale(image, label):
image = tf.cast(image, tf.float32)
image = tf.image.resize(image, [IMG_SIZE, IMG_SIZE])
image = (image / 255.0)
return image, label
มากำหนดฟังก์ชัน augment
ที่สามารถใช้การแปลงแบบสุ่มกับรูปภาพได้ ฟังก์ชันนี้จะใช้กับชุดข้อมูลในขั้นตอนต่อไป
def augment(image_label, seed):
image, label = image_label
image, label = resize_and_rescale(image, label)
image = tf.image.resize_with_crop_or_pad(image, IMG_SIZE + 6, IMG_SIZE + 6)
# Make a new seed.
new_seed = tf.random.experimental.stateless_split(seed, num=1)[0, :]
# Random crop back to the original size.
image = tf.image.stateless_random_crop(
image, size=[IMG_SIZE, IMG_SIZE, 3], seed=seed)
# Random brightness.
image = tf.image.stateless_random_brightness(
image, max_delta=0.5, seed=new_seed)
image = tf.clip_by_value(image, 0, 1)
return image, label
ตัวเลือกที่ 1: การใช้ tf.data.experimental.Counter
สร้างวัตถุ tf.data.experimental.Counter
(เรียกมันว่า counter
) และ Dataset.zip
ชุดข้อมูลด้วย (counter, counter)
เพื่อให้แน่ใจว่ารูปภาพแต่ละรูปในชุดข้อมูลเชื่อมโยงกับค่าที่ไม่ซ้ำกัน (ของรูปร่าง (2,)
) ตามตัว counter
ซึ่งต่อมาสามารถส่งผ่านไปยังฟังก์ชัน augment
เป็นค่า seed
ต้นสำหรับการแปลงแบบสุ่ม
# Create a `Counter` object and `Dataset.zip` it together with the training set.
counter = tf.data.experimental.Counter()
train_ds = tf.data.Dataset.zip((train_datasets, (counter, counter)))
แมปฟังก์ชัน augment
กับชุดข้อมูลการฝึกอบรม:
train_ds = (
train_ds
.shuffle(1000)
.map(augment, num_parallel_calls=AUTOTUNE)
.batch(batch_size)
.prefetch(AUTOTUNE)
)
val_ds = (
val_ds
.map(resize_and_rescale, num_parallel_calls=AUTOTUNE)
.batch(batch_size)
.prefetch(AUTOTUNE)
)
test_ds = (
test_ds
.map(resize_and_rescale, num_parallel_calls=AUTOTUNE)
.batch(batch_size)
.prefetch(AUTOTUNE)
)
ตัวเลือก 2: ใช้ tf.random.Generator
- สร้างอ็อบเจ็กต์
tf.random.Generator
ด้วยค่าseed
เริ่มต้น การเรียกใช้ฟังก์ชันmake_seeds
บนอ็อบเจ็กต์ตัวสร้างเดียวกันจะส่งกลับค่าseed
ใหม่ที่ไม่ซ้ำกันเสมอ - กำหนดฟังก์ชัน wrapper ที่: 1) เรียกใช้ฟังก์ชัน
make_seeds
; และ 2) ส่งผ่านค่าseed
ที่สร้างขึ้นใหม่ไปยังฟังก์ชันaugment
สำหรับการแปลงแบบสุ่ม
# Create a generator.
rng = tf.random.Generator.from_seed(123, alg='philox')
# Create a wrapper function for updating seeds.
def f(x, y):
seed = rng.make_seeds(2)[0]
image, label = augment((x, y), seed)
return image, label
ตัวยึดตำแหน่ง52 แมปฟังก์ชัน wrapper f
กับชุดข้อมูลการฝึก และฟังก์ชัน resize_and_rescale
กับชุดตรวจสอบและทดสอบ:
train_ds = (
train_datasets
.shuffle(1000)
.map(f, num_parallel_calls=AUTOTUNE)
.batch(batch_size)
.prefetch(AUTOTUNE)
)
val_ds = (
val_ds
.map(resize_and_rescale, num_parallel_calls=AUTOTUNE)
.batch(batch_size)
.prefetch(AUTOTUNE)
)
test_ds = (
test_ds
.map(resize_and_rescale, num_parallel_calls=AUTOTUNE)
.batch(batch_size)
.prefetch(AUTOTUNE)
)
ตอนนี้ชุดข้อมูลเหล่านี้สามารถใช้ในการฝึกโมเดลดังที่แสดงไว้ก่อนหน้านี้
ขั้นตอนถัดไป
บทช่วยสอนนี้สาธิตการเพิ่มข้อมูลโดยใช้เลเยอร์การประมวลผลล่วงหน้าของ Keras และ tf.image
- หากต้องการเรียนรู้วิธีรวมเลเยอร์การประมวลผลล่วงหน้าไว้ในโมเดลของคุณ โปรดดูบทแนะนำการ จัดหมวดหมู่รูปภาพ
- คุณอาจสนใจที่จะเรียนรู้ว่าการประมวลผลล่วงหน้าของเลเยอร์สามารถช่วยคุณจัดประเภทข้อความได้อย่างไร ดังที่แสดงในบทแนะนำการ จัดประเภทข้อความพื้นฐาน
- คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับ
tf.data
ใน คู่มือ นี้ และคุณสามารถเรียนรู้วิธีกำหนดค่าไพพ์ไลน์อินพุตของคุณเพื่อประสิทธิภาพ ที่นี่