การเสริมข้อมูล

ดูบน TensorFlow.org ทำงานใน Google Colab ดูแหล่งที่มาบน GitHub ดาวน์โหลดโน๊ตบุ๊ค

ภาพรวม

บทช่วยสอนนี้สาธิตการเพิ่มข้อมูล: เทคนิคในการเพิ่มความหลากหลายของชุดการฝึกของคุณโดยใช้การแปลงแบบสุ่ม (แต่เหมือนจริง) เช่น การหมุนภาพ คุณจะได้เรียนรู้วิธีใช้การเพิ่มข้อมูลในสองวิธี ครั้งแรกที่คุณจะใช้ เลเยอร์ Keras กระบวนการเตรียมการผลิต ถัดไปคุณจะใช้ tf.image

ติดตั้ง

import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds

from tensorflow.keras import layers
2021-07-31 01:20:29.398577: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0

ดาวน์โหลดชุดข้อมูล

กวดวิชานี้ใช้ tf_flowers ชุด เพื่ออำนวยความสะดวกให้ดาวน์โหลดชุดข้อมูลโดยใช้ TensorFlow ชุดข้อมูล หากคุณต้องการที่จะเรียนรู้เกี่ยวกับวิธีการอื่น ๆ ของการนำเข้าข้อมูลให้ดู ภาพโหลด กวดวิชา

(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,
)
2021-07-31 01:20:32.658409: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcuda.so.1
2021-07-31 01:20:33.245494: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-31 01:20:33.246357: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1733] Found device 0 with properties: 
pciBusID: 0000:00:05.0 name: Tesla V100-SXM2-16GB computeCapability: 7.0
coreClock: 1.53GHz coreCount: 80 deviceMemorySize: 15.78GiB deviceMemoryBandwidth: 836.37GiB/s
2021-07-31 01:20:33.246390: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0
2021-07-31 01:20:33.249453: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublas.so.11
2021-07-31 01:20:33.249541: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublasLt.so.11
2021-07-31 01:20:33.250610: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcufft.so.10
2021-07-31 01:20:33.250929: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcurand.so.10
2021-07-31 01:20:33.251983: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcusolver.so.11
2021-07-31 01:20:33.252852: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcusparse.so.11
2021-07-31 01:20:33.253031: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudnn.so.8
2021-07-31 01:20:33.253121: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-31 01:20:33.253980: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-31 01:20:33.254770: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1871] Adding visible gpu devices: 0
2021-07-31 01:20:33.255502: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 AVX512F FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2021-07-31 01:20:33.256126: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-31 01:20:33.256945: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1733] Found device 0 with properties: 
pciBusID: 0000:00:05.0 name: Tesla V100-SXM2-16GB computeCapability: 7.0
coreClock: 1.53GHz coreCount: 80 deviceMemorySize: 15.78GiB deviceMemoryBandwidth: 836.37GiB/s
2021-07-31 01:20:33.257035: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-31 01:20:33.257857: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-31 01:20:33.258642: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1871] Adding visible gpu devices: 0
2021-07-31 01:20:33.258683: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0
2021-07-31 01:20:33.827497: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1258] Device interconnect StreamExecutor with strength 1 edge matrix:
2021-07-31 01:20:33.827531: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1264]      0 
2021-07-31 01:20:33.827538: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1277] 0:   N 
2021-07-31 01:20:33.827734: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-31 01:20:33.828649: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-31 01:20:33.829480: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-31 01:20:33.830357: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1418] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 14646 MB memory) -> physical GPU (device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:05.0, compute capability: 7.0)

ชุดข้อมูลดอกไม้มีห้าคลาส

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))
2021-07-31 01:20:33.935374: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:176] None of the MLIR Optimization Passes are enabled (registered 2)
2021-07-31 01:20:33.935908: I tensorflow/core/platform/profile_utils/cpu_utils.cc:114] CPU Frequency: 2000160000 Hz
2021-07-31 01:20:34.470092: 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.

png

ใช้เลเยอร์การประมวลผลล่วงหน้าของ Keras

การปรับขนาดและการปรับขนาด

คุณสามารถใช้ preprocessing ชั้นเพื่อ ปรับขนาด ภาพของคุณให้เป็นรูปร่างที่สอดคล้องกันและ rescale ค่าพิกเซล

IMG_SIZE = 180

resize_and_rescale = tf.keras.Sequential([
  layers.experimental.preprocessing.Resizing(IMG_SIZE, IMG_SIZE),
  layers.experimental.preprocessing.Rescaling(1./255)
])

คุณสามารถเห็นผลของการใช้เลเยอร์เหล่านี้กับรูปภาพ

result = resize_and_rescale(image)
_ = plt.imshow(result)

png

คุณสามารถตรวจสอบพิกเซลอยู่ใน [0-1]

print("Min and max pixel values:", result.numpy().min(), result.numpy().max())
Min and max pixel values: 0.0 1.0

การเสริมข้อมูล

คุณสามารถใช้เลเยอร์การประมวลผลล่วงหน้าสำหรับการเพิ่มข้อมูลได้เช่นกัน

มาสร้างเลเยอร์การประมวลผลล่วงหน้าสองสามเลเยอร์แล้วนำไปใช้กับรูปภาพเดียวกันซ้ำๆ

data_augmentation = tf.keras.Sequential([
  layers.experimental.preprocessing.RandomFlip("horizontal_and_vertical"),
  layers.experimental.preprocessing.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")

png

มีความหลากหลายของ preprocessing เป็น ชั้น ที่คุณสามารถใช้สำหรับการเสริมข้อมูลรวมทั้ง layers.RandomContrast , layers.RandomCrop , layers.RandomZoom และอื่น ๆ

สองตัวเลือกเพื่อใช้เลเยอร์การประมวลผลล่วงหน้า

มีสองวิธีที่คุณสามารถใช้เลเยอร์การประมวลผลล่วงหน้าเหล่านี้ โดยมีข้อเสียที่สำคัญ

ตัวเลือกที่ 1: ทำให้เลเยอร์ก่อนการประมวลผลเป็นส่วนหนึ่งของโมเดลของคุณ

model = tf.keras.Sequential([
  resize_and_rescale,
  data_augmentation,
  layers.Conv2D(16, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  # Rest of your model
])

มีสองประเด็นสำคัญที่ควรทราบในกรณีนี้:

  • การเพิ่มข้อมูลจะทำงานบนอุปกรณ์ ซิงโครนัสกับเลเยอร์ที่เหลือของคุณ และได้รับประโยชน์จากการเร่งความเร็วของ GPU

  • เมื่อคุณส่งออกรูปแบบของคุณโดยใช้ model.save , ชั้น preprocessing จะถูกบันทึกไว้พร้อมกับส่วนที่เหลือของรูปแบบของคุณ หากคุณปรับใช้โมเดลนี้ในภายหลัง โมเดลจะสร้างมาตรฐานให้กับรูปภาพโดยอัตโนมัติ (ตามการกำหนดค่าเลเยอร์ของคุณ) วิธีนี้ช่วยให้คุณไม่ต้องพยายามปรับใช้ลอจิกฝั่งเซิร์ฟเวอร์อีกครั้ง

ตัวเลือกที่ 2: ใช้เลเยอร์การประมวลผลล่วงหน้ากับชุดข้อมูลของคุณ

aug_ds = train_ds.map(
  lambda x, y: (resize_and_rescale(x, training=True), y))

ด้วยวิธีนี้คุณจะใช้ Dataset.map เพื่อสร้างชุดข้อมูลที่อัตราผลตอบแทนกระบวนการของภาพยิ่ง ในกรณีนี้:

  • การเพิ่มข้อมูลจะเกิดขึ้นแบบอะซิงโครนัสบน CPU และไม่มีการบล็อก คุณสามารถซ้อนทับกันของรูปแบบการฝึกอบรมของคุณบน GPU ที่มีข้อมูล preprocessing ใช้ Dataset.prefetch แสดงด้านล่าง
  • ในกรณีนี้ชั้น prepreprocessing จะไม่ถูกส่งออกกับรูปแบบเมื่อคุณเรียก model.save คุณจะต้องแนบไฟล์เหล่านี้กับโมเดลของคุณก่อนที่จะบันทึกหรือปรับใช้ใหม่ทางฝั่งเซิร์ฟเวอร์ หลังการฝึก คุณสามารถแนบเลเยอร์การประมวลผลล่วงหน้าก่อนส่งออกได้

คุณสามารถค้นหาตัวอย่างของตัวเลือกแรกในที่ จัดหมวดหมู่ภาพ กวดวิชา มาสาธิตตัวเลือกที่สองกันที่นี่

ใช้เลเยอร์การประมวลผลล่วงหน้ากับชุดข้อมูล

กำหนดค่ารถไฟ การตรวจสอบ และทดสอบชุดข้อมูลด้วยเลเยอร์การประมวลผลล่วงหน้าที่คุณสร้างขึ้นด้านบน คุณยังกำหนดค่าชุดข้อมูลเพื่อประสิทธิภาพ โดยใช้การอ่านแบบขนานและการดึงข้อมูลล่วงหน้าแบบบัฟเฟอร์เพื่อให้แบตช์จากดิสก์ที่ไม่มี I/O กลายเป็นการบล็อก คุณสามารถเรียนรู้ประสิทธิภาพการทำงานของชุดข้อมูลที่มากขึ้นใน การปฏิบัติงานที่ดีขึ้นด้วย API tf.data คู่มือ

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 prefecting 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)

ฝึกโมเดล

เพื่อความสมบูรณ์ ตอนนี้คุณจะต้องฝึกโมเดลโดยใช้ชุดข้อมูลเหล่านี้ โมเดลนี้ไม่ได้รับการปรับแต่งเพื่อความแม่นยำ (เป้าหมายคือเพื่อแสดงกลไกให้คุณเห็น)

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)
])
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
2021-07-31 01:20:39.448244: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudnn.so.8
2021-07-31 01:20:41.475212: I tensorflow/stream_executor/cuda/cuda_dnn.cc:359] Loaded cuDNN version 8100
2021-07-31 01:20:46.496035: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublas.so.11
2021-07-31 01:20:46.860481: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublasLt.so.11
92/92 [==============================] - 17s 66ms/step - loss: 1.3434 - accuracy: 0.4271 - val_loss: 1.1534 - val_accuracy: 0.5368
Epoch 2/5
92/92 [==============================] - 3s 27ms/step - loss: 1.0960 - accuracy: 0.5565 - val_loss: 1.0718 - val_accuracy: 0.5695
Epoch 3/5
92/92 [==============================] - 3s 26ms/step - loss: 1.0115 - accuracy: 0.5988 - val_loss: 1.0322 - val_accuracy: 0.6022
Epoch 4/5
92/92 [==============================] - 3s 27ms/step - loss: 0.9503 - accuracy: 0.6202 - val_loss: 0.8811 - val_accuracy: 0.6730
Epoch 5/5
92/92 [==============================] - 3s 27ms/step - loss: 0.8758 - accuracy: 0.6570 - val_loss: 0.8760 - val_accuracy: 0.6485
loss, acc = model.evaluate(test_ds)
print("Accuracy", acc)
12/12 [==============================] - 1s 13ms/step - loss: 0.8319 - accuracy: 0.6812
Accuracy 0.6811988949775696

การเพิ่มข้อมูลที่กำหนดเอง

คุณยังสามารถสร้างเลเยอร์การเพิ่มข้อมูลที่กำหนดเองได้อีกด้วย บทช่วยสอนนี้แสดงสองวิธีในการทำเช่นนั้น ครั้งแรกที่คุณจะสร้าง layers.Lambda ชั้น นี่เป็นวิธีที่ดีในการเขียนโค้ดที่กระชับ ถัดไปคุณจะเขียนเลเยอร์ใหม่ผ่าน subclassing ซึ่งจะช่วยให้คุณสามารถควบคุมได้มากขึ้น ทั้งสองเลเยอร์จะสุ่มสลับสีในภาพตามความน่าจะเป็น

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")

png

ถัดไปใช้ชั้นที่กำหนดเองโดย subclassing

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])

png

เลเยอร์ทั้งสองนี้สามารถใช้ได้ตามที่อธิบายไว้ในตัวเลือกที่ 1 และ 2 ด้านบน

ใช้ tf.image

ดังกล่าวข้างต้น layers.preprocessing สาธารณูปโภคมีความสะดวก สำหรับการควบคุมปลีกย่อยคุณสามารถเขียนท่อเสริมข้อมูลของคุณเองหรือชั้นใช้ tf.data และ tf.image นอกจากนี้คุณยังอาจต้องการตรวจสอบ TensorFlow Addons ภาพ: การดำเนินงาน และ TensorFlow I / O: สีพื้นที่การแปลง

เนื่องจากก่อนหน้านี้ชุดข้อมูลดอกไม้ได้รับการกำหนดค่าด้วยการเพิ่มข้อมูล ให้นำเข้าใหม่เพื่อเริ่มต้นใหม่

(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))
2021-07-31 01:21:08.829596: 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.

png

ลองใช้ฟังก์ชันต่อไปนี้ในการแสดงภาพและเปรียบเทียบภาพต้นฉบับและภาพเสริมกัน

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)

การเสริมข้อมูล

พลิกภาพ

พลิกภาพในแนวตั้งหรือแนวนอน

flipped = tf.image.flip_left_right(image)
visualize(image, flipped)

png

ระดับสีเทาของภาพ

ภาพสีเทา

grayscaled = tf.image.rgb_to_grayscale(image)
visualize(image, tf.squeeze(grayscaled))
_ = plt.colorbar()

png

อิ่มตัวภาพ

ทำให้ภาพอิ่มตัวโดยระบุปัจจัยความอิ่มตัว

saturated = tf.image.adjust_saturation(image, 3)
visualize(image, saturated)

png

เปลี่ยนความสว่างของภาพ

เปลี่ยนความสว่างของภาพโดยระบุปัจจัยความสว่าง

bright = tf.image.adjust_brightness(image, 0.4)
visualize(image, bright)

png

ครอบตัดรูปภาพตรงกลาง

ครอบตัดรูปภาพจากกึ่งกลางไปยังส่วนรูปภาพที่คุณต้องการ

cropped = tf.image.central_crop(image, central_fraction=0.5)
visualize(image,cropped)

png

หมุนภาพ

หมุนรูปภาพ 90 องศา

rotated = tf.image.rot90(image)
visualize(image, rotated)

png

การแปลงแบบสุ่ม

การใช้การแปลงแบบสุ่มกับรูปภาพสามารถช่วยทำให้ภาพรวมและขยายชุดข้อมูลได้กว้างขึ้น ปัจจุบัน tf.image API ให้ 8 เช่นการดำเนินงานภาพแบบสุ่ม (OPS):

ops ภาพสุ่มเหล่านี้ใช้งานได้อย่างหมดจด: เอาต์พุตขึ้นอยู่กับอินพุตเท่านั้น ซึ่งทำให้ง่ายต่อการใช้งานในไพพ์ไลน์อินพุตที่มีประสิทธิภาพสูงและกำหนดได้ พวกเขาต้องมี seed ค่าป้อนข้อมูลในแต่ละขั้นตอน ได้รับเดียวกัน seed พวกเขากลับผลลัพธ์เดียวกันอิสระของวิธีการหลายครั้งที่พวกเขาจะเรียกว่า

ในส่วนต่อไปนี้ คุณจะ:

  1. ดูตัวอย่างการใช้การดำเนินการรูปภาพแบบสุ่มเพื่อแปลงรูปภาพ และ
  2. สาธิตวิธีการใช้การแปลงแบบสุ่มกับชุดข้อมูลการฝึกอบรม

สุ่มเปลี่ยนความสว่างของภาพ

สุ่มเปลี่ยนความสว่างของ image โดยการให้ปัจจัยที่สว่างและ 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)

png

png

png

สุ่มเปลี่ยนความคมชัดของภาพ

สุ่มปรับความคมชัดของ image โดยการให้ช่วงความคมชัดและ 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)

png

png

png

ครอบตัดรูปภาพแบบสุ่ม

สุ่มตัด image โดยการให้เป้าหมาย size และ seed ส่วนที่ได้รับการตัดออกจาก image ที่สุ่มเลือกที่ offset และมีความเกี่ยวข้องกับที่ได้รับ 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)

png

png

png

ใช้การเสริมกับชุดข้อมูล

เรามาดาวน์โหลดชุดข้อมูลภาพกันก่อนอีกครั้งในกรณีที่มีการแก้ไขในส่วนก่อนหน้า

(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

Let 's ยังกำหนด 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 ) และ zip ชุดข้อมูลที่มี (counter, counter) นี้จะให้แน่ใจว่าภาพในชุดข้อมูลที่แต่ละคนได้รับการเชื่อมโยงกับค่าที่ไม่ซ้ำ (ของรูปร่าง (2,) ) ตาม counter ซึ่งต่อมาได้รับการผ่านเข้าสู่ augment การทำงานเป็น seed คุ้มค่าต่อการเปลี่ยนแปลงแบบสุ่ม

# Create counter and zip together with train dataset
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 วัตถุที่มี intial seed คุ้มค่า โทร make_seeds ทำงานบนกำเนิดเดียวกันผลตอบแทนวัตถุใหม่ที่ไม่ซ้ำกัน seed คุ้มค่าเสมอ กำหนดฟังก์ชั่นเสื้อคลุมที่ 1) เรียก make_seeds ฟังก์ชั่นและ 2) ผ่านที่สร้างใหม่ seed ค่าเป็นการ augment ฟังก์ชั่นสำหรับการแปลงแบบสุ่ม

# Create a generator
rng = tf.random.Generator.from_seed(123, alg='philox')
# 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

แผนที่ฟังก์ชั่นเสื้อคลุม f ไปชุดข้อมูลการฝึกอบรม

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 ต้องการเรียนรู้วิธีที่จะรวม preprocessing ชั้นภายในรูปแบบของคุณให้ดู ภาพการจำแนกประเภท กวดวิชา นอกจากนี้คุณยังอาจจะสนใจในการเรียนรู้วิธีชั้น preprocessing สามารถช่วยให้คุณข้อความประเภทดังที่แสดงใน ข้อความพื้นฐานการจำแนกประเภท กวดวิชา คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับ tf.data ในนี้ คู่มือ และคุณสามารถเรียนรู้วิธีการกำหนดค่าท่อป้อนข้อมูลของคุณสำหรับการทำงาน ที่นี่