โหลดและประมวลผลภาพล่วงหน้า

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

บทช่วยสอนนี้แสดงวิธีการโหลดและประมวลผลชุดข้อมูลรูปภาพล่วงหน้าในสามวิธี ครั้งแรกที่คุณจะใช้ระดับสูง Keras preprocessing สาธารณูปโภค และ ชั้น ที่จะอ่านไดเรกทอรีของภาพบนดิสก์ ถัดไปคุณจะเขียนท่อป้อนข้อมูลของคุณเองตั้งแต่เริ่มต้น ใช้ tf.data สุดท้ายคุณจะดาวน์โหลดชุดข้อมูลจากขนาดใหญ่ แคตตาล็อก ที่มีอยู่ใน TensorFlow ชุดข้อมูล

ติดตั้ง

import numpy as np
import os
import PIL
import PIL.Image
import tensorflow as tf
import tensorflow_datasets as tfds
print(tf.__version__)
2.5.0

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

บทช่วยสอนนี้ใช้ชุดข้อมูลภาพถ่ายดอกไม้หลายพันภาพ ชุดข้อมูลดอกไม้ประกอบด้วยไดเร็กทอรีย่อย 5 ไดเร็กทอรี หนึ่งไดเร็กทอรีต่อคลาส:

flowers_photos/
  daisy/
  dandelion/
  roses/
  sunflowers/
  tulips/
import pathlib
dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"
data_dir = tf.keras.utils.get_file(origin=dataset_url, 
                                   fname='flower_photos', 
                                   untar=True)
data_dir = pathlib.Path(data_dir)
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz
228818944/228813984 [==============================] - 2s 0us/step

หลังจากดาวน์โหลด (218MB) คุณควรมีสำเนาภาพถ่ายดอกไม้ที่พร้อมใช้งาน มีทั้งหมด 3,670 ภาพ:

image_count = len(list(data_dir.glob('*/*.jpg')))
print(image_count)
3670

แต่ละไดเร็กทอรีมีรูปภาพของดอกไม้ประเภทนั้น นี่คือดอกกุหลาบบางส่วน:

roses = list(data_dir.glob('roses/*'))
PIL.Image.open(str(roses[0]))

png

roses = list(data_dir.glob('roses/*'))
PIL.Image.open(str(roses[1]))

png

โหลดใช้ tf.keras.preprocessing

โหลด Let 's ภาพเหล่านี้ออกจากดิสก์โดยใช้ tf.keras.preprocessing.image_dataset_from_directory

สร้างชุดข้อมูล

กำหนดพารามิเตอร์บางอย่างสำหรับตัวโหลด:

batch_size = 32
img_height = 180
img_width = 180

แนวทางปฏิบัติที่ดีในการใช้การแยกการตรวจสอบความถูกต้องเมื่อพัฒนาแบบจำลองของคุณ คุณจะใช้รูปภาพ 80% สำหรับการฝึกอบรมและ 20% สำหรับการตรวจสอบ

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="training",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)
Found 3670 files belonging to 5 classes.
Using 2936 files for training.
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="validation",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)
Found 3670 files belonging to 5 classes.
Using 734 files for validation.

คุณสามารถค้นหาชื่อชั้นใน class_names แอตทริบิวต์ในชุดข้อมูลเหล่านี้

class_names = train_ds.class_names
print(class_names)
['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips']

เห็นภาพข้อมูล

นี่คือ 9 ภาพแรกจากชุดข้อมูลการฝึกอบรม

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 10))
for images, labels in train_ds.take(1):
  for i in range(9):
    ax = plt.subplot(3, 3, i + 1)
    plt.imshow(images[i].numpy().astype("uint8"))
    plt.title(class_names[labels[i]])
    plt.axis("off")

png

คุณสามารถฝึกอบรมรูปแบบโดยใช้ชุดข้อมูลเหล่านี้โดยผ่านพวกเขาไป model.fit (แสดงในภายหลังในการกวดวิชานี้) หากต้องการ คุณยังสามารถวนซ้ำชุดข้อมูลด้วยตนเองและเรียกค้นชุดรูปภาพ:

for image_batch, labels_batch in train_ds:
  print(image_batch.shape)
  print(labels_batch.shape)
  break
(32, 180, 180, 3)
(32,)

image_batch เป็นเมตริกซ์ของรูปทรง (32, 180, 180, 3) นี่คือชุดของ 32 ภาพของรูปร่าง 180x180x3 (คน referes มิติสุดท้ายที่ช่องสี RGB) label_batch เป็นเมตริกซ์ของรูปทรง (32,) เหล่านี้เป็นป้ายที่สอดคล้องกับ 32 ภาพ

ทำให้ข้อมูลเป็นมาตรฐาน

ค่าช่อง RGB อยู่ใน [0, 255] ช่วง ไม่เหมาะสำหรับโครงข่ายประสาทเทียม โดยทั่วไป คุณควรพยายามทำให้ค่าอินพุตของคุณมีขนาดเล็ก ที่นี่คุณจะค่ามาตรฐานที่จะอยู่ใน [0, 1] ช่วงโดยใช้ tf.keras.layers.experimental.preprocessing.Rescaling ชั้น

normalization_layer = tf.keras.layers.experimental.preprocessing.Rescaling(1./255)

มีสองวิธีในการใช้เลเยอร์นี้ คุณสามารถใช้กับชุดข้อมูลได้โดยเรียกแผนที่:

normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
image_batch, labels_batch = next(iter(normalized_ds))
first_image = image_batch[0]
# Notice the pixels values are now in `[0,1]`.
print(np.min(first_image), np.max(first_image))
0.0 0.96902645

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

กำหนดค่าชุดข้อมูลสำหรับประสิทธิภาพ

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

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

.prefetch() คาบเกี่ยวข้อมูล preprocessing และการดำเนินการในขณะที่รูปแบบการฝึกอบรม

ผู้อ่านที่สนใจสามารถเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการทั้งสองเช่นเดียวกับวิธีการแคชข้อมูลไปยังดิสก์ใน คู่มือข้อมูลประสิทธิภาพ

AUTOTUNE = tf.data.AUTOTUNE

train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

ฝึกโมเดล

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

num_classes = 5

model = tf.keras.Sequential([
  tf.keras.layers.experimental.preprocessing.Rescaling(1./255),
  tf.keras.layers.Conv2D(32, 3, activation='relu'),
  tf.keras.layers.MaxPooling2D(),
  tf.keras.layers.Conv2D(32, 3, activation='relu'),
  tf.keras.layers.MaxPooling2D(),
  tf.keras.layers.Conv2D(32, 3, activation='relu'),
  tf.keras.layers.MaxPooling2D(),
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(num_classes)
])
model.compile(
  optimizer='adam',
  loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True),
  metrics=['accuracy'])
model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)
Epoch 1/3
92/92 [==============================] - 11s 27ms/step - loss: 1.3361 - accuracy: 0.4486 - val_loss: 1.1087 - val_accuracy: 0.5286
Epoch 2/3
92/92 [==============================] - 1s 11ms/step - loss: 1.0482 - accuracy: 0.5872 - val_loss: 1.0247 - val_accuracy: 0.5913
Epoch 3/3
92/92 [==============================] - 1s 11ms/step - loss: 0.9310 - accuracy: 0.6383 - val_loss: 0.9354 - val_accuracy: 0.6267
<tensorflow.python.keras.callbacks.History at 0x7fe9ad142dd0>

คุณอาจสังเกตเห็นว่าความแม่นยำในการตรวจสอบความถูกต้องนั้นต่ำเมื่อเทียบกับความแม่นยำในการฝึก ซึ่งบ่งชี้ว่าแบบจำลองของคุณมีมากเกินไป คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับ overfitting และวิธีการลดความมันในการ กวดวิชา

ใช้ tf.data สำหรับการควบคุมปลีกย่อย

ดังกล่าวข้างต้น tf.keras.preprocessing สาธารณูปโภคเป็นวิธีที่สะดวกในการสร้าง tf.data.Dataset จากไดเรกทอรีของภาพ สำหรับการควบคุมเม็ดปลีกย่อยคุณสามารถเขียนของคุณเองโดยใช้ท่อป้อนข้อมูล tf.data ส่วนนี้แสดงวิธีการดำเนินการดังกล่าว โดยเริ่มจากเส้นทางของไฟล์จากไฟล์ TGZ ที่คุณดาวน์โหลดมาก่อนหน้านี้

list_ds = tf.data.Dataset.list_files(str(data_dir/'*/*'), shuffle=False)
list_ds = list_ds.shuffle(image_count, reshuffle_each_iteration=False)
for f in list_ds.take(5):
  print(f.numpy())
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/16970837587_4a9d8500d7.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/8337607102_d9e0fa887e.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/5032376020_2ed312306c.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/7166606598_5d2cd307c3.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/235651658_a7b3e7cbdd.jpg'

โครงสร้างต้นไม้ของไฟล์ที่สามารถใช้ในการรวบรวม class_names รายการ

class_names = np.array(sorted([item.name for item in data_dir.glob('*') if item.name != "LICENSE.txt"]))
print(class_names)
['daisy' 'dandelion' 'roses' 'sunflowers' 'tulips']

แยกชุดข้อมูลออกเป็นรถไฟและการตรวจสอบความถูกต้อง:

val_size = int(image_count * 0.2)
train_ds = list_ds.skip(val_size)
val_ds = list_ds.take(val_size)

คุณสามารถดูความยาวของชุดข้อมูลแต่ละชุดได้ดังนี้:

print(tf.data.experimental.cardinality(train_ds).numpy())
print(tf.data.experimental.cardinality(val_ds).numpy())
2936
734

เขียนฟังก์ชั่นสั้น ๆ ที่แปลงไฟล์เส้นทางไปยัง (img, label) คู่:

def get_label(file_path):
  # convert the path to a list of path components
  parts = tf.strings.split(file_path, os.path.sep)
  # The second to last is the class-directory
  one_hot = parts[-2] == class_names
  # Integer encode the label
  return tf.argmax(one_hot)
def decode_img(img):
  # convert the compressed string to a 3D uint8 tensor
  img = tf.io.decode_jpeg(img, channels=3)
  # resize the image to the desired size
  return tf.image.resize(img, [img_height, img_width])
def process_path(file_path):
  label = get_label(file_path)
  # load the raw data from the file as a string
  img = tf.io.read_file(file_path)
  img = decode_img(img)
  return img, label

ใช้ Dataset.map เพื่อสร้างชุดข้อมูลของ image, label คู่

# Set `num_parallel_calls` so multiple images are loaded/processed in parallel.
train_ds = train_ds.map(process_path, num_parallel_calls=AUTOTUNE)
val_ds = val_ds.map(process_path, num_parallel_calls=AUTOTUNE)
for image, label in train_ds.take(1):
  print("Image shape: ", image.numpy().shape)
  print("Label: ", label.numpy())
Image shape:  (180, 180, 3)
Label:  2

กำหนดค่าชุดข้อมูลสำหรับประสิทธิภาพ

ในการฝึกโมเดลด้วยชุดข้อมูลนี้ คุณจะต้องการข้อมูล:

  • ที่จะสับเปลี่ยนกันอย่างดี
  • ที่จะแบทช์
  • แบทช์ที่จะสามารถใช้ได้โดยเร็วที่สุด

คุณสมบัติเหล่านี้สามารถเพิ่มการใช้ tf.data API สำหรับรายละเอียดเพิ่มเติมโปรดดูที่ การป้อนข้อมูลผลการดำเนินงานท่อส่ง คู่มือ

def configure_for_performance(ds):
  ds = ds.cache()
  ds = ds.shuffle(buffer_size=1000)
  ds = ds.batch(batch_size)
  ds = ds.prefetch(buffer_size=AUTOTUNE)
  return ds

train_ds = configure_for_performance(train_ds)
val_ds = configure_for_performance(val_ds)

เห็นภาพข้อมูล

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

image_batch, label_batch = next(iter(train_ds))

plt.figure(figsize=(10, 10))
for i in range(9):
  ax = plt.subplot(3, 3, i + 1)
  plt.imshow(image_batch[i].numpy().astype("uint8"))
  label = label_batch[i]
  plt.title(class_names[label])
  plt.axis("off")

png

ฝึกโมเดลต่อไป

ตอนนี้คุณได้สร้างคล้ายตนเอง tf.data.Dataset หนึ่งที่สร้างขึ้นโดย keras.preprocessing ดังกล่าวข้างต้น คุณสามารถฝึกโมเดลต่อได้ เช่นเดียวกับเมื่อก่อน คุณจะฝึกเพียงไม่กี่ช่วงเพื่อให้เวลาทำงานสั้นลง

model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)
Epoch 1/3
92/92 [==============================] - 2s 20ms/step - loss: 0.8191 - accuracy: 0.6734 - val_loss: 0.7638 - val_accuracy: 0.7221
Epoch 2/3
92/92 [==============================] - 1s 12ms/step - loss: 0.6748 - accuracy: 0.7432 - val_loss: 0.8300 - val_accuracy: 0.6744
Epoch 3/3
92/92 [==============================] - 1s 12ms/step - loss: 0.5102 - accuracy: 0.8099 - val_loss: 0.7650 - val_accuracy: 0.7016
<tensorflow.python.keras.callbacks.History at 0x7fe9acfb0d50>

การใช้ชุดข้อมูล TensorFlow

จนถึงตอนนี้ บทช่วยสอนนี้เน้นไปที่การโหลดข้อมูลออกจากดิสก์ นอกจากนี้คุณยังสามารถหาชุดที่จะใช้งานโดยการสำรวจขนาดใหญ่ แคตตาล็อก ของชุดข้อมูลที่ง่ายต่อการดาวน์โหลดได้ที่ TensorFlow ชุดข้อมูล เนื่องจากคุณได้โหลดชุดข้อมูล Flowers ออกจากดิสก์ก่อนหน้านี้ มาดูวิธีการนำเข้าด้วยชุดข้อมูล TensorFlow

ดาวน์โหลดดอกไม้ ชุดข้อมูลที่ ใช้ 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,
)

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

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

png

เช่นเคย อย่าลืมแบทช์ สับเปลี่ยน และกำหนดค่าแต่ละชุดข้อมูลเพื่อประสิทธิภาพ

train_ds = configure_for_performance(train_ds)
val_ds = configure_for_performance(val_ds)
test_ds = configure_for_performance(test_ds)

คุณสามารถค้นหาตัวอย่างที่สมบูรณ์ของการทำงานกับชุดดอกไม้และ TensorFlow ชุดข้อมูลโดยการเยี่ยมชม ข้อมูลเสริม กวดวิชา

ขั้นตอนถัดไป

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