มีคำถาม? เชื่อมต่อกับชุมชนที่ฟอรัม TensorFlow เยี่ยมชมฟอรัม

โหลดภาพ

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

บทช่วยสอนนี้แสดงวิธีการโหลดและประมวลผลชุดข้อมูลรูปภาพล่วงหน้าในสามวิธี ขั้นแรก คุณจะใช้ ยูทิลิตี้ และ เลเยอร์การ ประมวลผลล่วงหน้าของ Keras ระดับสูงเพื่ออ่านไดเร็กทอรีของรูปภาพบนดิสก์ ถัดไป คุณจะเขียนไปป์ไลน์อินพุตของคุณเองตั้งแต่ต้นโดยใช้ 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 [==============================] - 6s 0us/step

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

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

โหลดโดยใช้ 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) นี่คือชุดรูปภาพขนาด 180x180x3 จำนวน 32 รูป (มิติสุดท้ายหมายถึงช่องสี RGB) label_batch คือเทนเซอร์ของรูปร่าง (32,) ซึ่งเป็นป้ายกำกับที่สอดคล้องกับรูปภาพ 32 รูป

สร้างมาตรฐานข้อมูล

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

from tensorflow.keras import layers

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() ทับซ้อนการประมวลผลข้อมูลล่วงหน้าและการดำเนินการโมเดลขณะฝึก

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

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([
  layers.experimental.preprocessing.Rescaling(1./255),
  layers.Conv2D(32, 3, activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(32, 3, activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(32, 3, activation='relu'),
  layers.MaxPooling2D(),
  layers.Flatten(),
  layers.Dense(128, activation='relu'),
  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 [==============================] - 9s 27ms/step - loss: 1.3032 - accuracy: 0.4387 - val_loss: 1.1089 - val_accuracy: 0.5599
Epoch 2/3
92/92 [==============================] - 1s 11ms/step - loss: 1.0455 - accuracy: 0.5736 - val_loss: 1.0263 - val_accuracy: 0.5886
Epoch 3/3
92/92 [==============================] - 1s 11ms/step - loss: 0.8962 - accuracy: 0.6512 - val_loss: 0.9631 - val_accuracy: 0.6076
<tensorflow.python.keras.callbacks.History at 0x7f154400d9d0>

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

การใช้ tf.data เพื่อการควบคุมที่ละเอียดยิ่งขึ้น

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

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/sunflowers/6199086734_b7ddc65816_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/8744249948_36cb1969f8_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/4933823194_33f6e32c5a.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/15977362155_461030c196_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/6606820461_952c450f90_n.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.image.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 คู่ 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 สำหรับรายละเอียดเพิ่มเติม โปรดดูที่คู่มือ ประสิทธิภาพ ของ Input Pipeline

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

model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)
Epoch 1/3
92/92 [==============================] - 2s 19ms/step - loss: 0.7598 - accuracy: 0.7176 - val_loss: 0.7693 - val_accuracy: 0.6962
Epoch 2/3
92/92 [==============================] - 1s 11ms/step - loss: 0.5583 - accuracy: 0.7987 - val_loss: 0.7780 - val_accuracy: 0.7044
Epoch 3/3
92/92 [==============================] - 1s 11ms/step - loss: 0.3602 - accuracy: 0.8706 - val_loss: 0.8437 - val_accuracy: 0.7030
<tensorflow.python.keras.callbacks.History at 0x7f1499ce1ad0>

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

จนถึงตอนนี้ บทช่วยสอนนี้เน้นไปที่การโหลดข้อมูลออกจากดิสก์ คุณยังสามารถค้นหาชุดข้อมูลที่จะใช้โดยการสำรวจ แคตตาล็อก ขนาดใหญ่ของชุดข้อมูลที่ดาวน์โหลดง่ายได้ที่ TensorFlow Datasets เนื่องจากคุณได้โหลดชุดข้อมูล 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 คุณสามารถไปที่ คู่มือ นี้