بارگیری و پیش پردازش تصاویر

مشاهده در TensorFlow.org در Google Colab اجرا شود مشاهده منبع در GitHub دانلود دفترچه یادداشت

این آموزش نحوه بارگیری و پیش پردازش یک مجموعه داده تصویر را به سه روش نشان می دهد:

برپایی

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

مجموعه داده گل ها را دانلود کنید

این آموزش از مجموعه داده ای از چندین هزار عکس گل استفاده می کند. مجموعه داده گلها شامل پنج زیرمجموعه است، یکی در هر کلاس:

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)

پس از دانلود (218 مگابایت)، اکنون باید یک کپی از عکس های گل در دسترس داشته باشید. 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 بارگیری کنید

بیایید این تصاویر را با استفاده از ابزار مفید tf.keras.utils.image_dataset_from_directory از روی دیسک بارگذاری کنیم.

یک مجموعه داده ایجاد کنید

چند پارامتر برای لودر تعریف کنید:

batch_size = 32
img_height = 180
img_width = 180

استفاده از تقسیم اعتبار در هنگام توسعه مدل خود تمرین خوبی است. شما از 80 درصد تصاویر برای آموزش و 20 درصد برای اعتبار سنجی استفاده خواهید کرد.

train_ds = tf.keras.utils.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.utils.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']

داده ها را تجسم کنید

در اینجا نه تصویر اول از مجموعه داده آموزشی آمده است.

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 است (بعد آخر به کانال های رنگی RGB اشاره دارد). label_batch یک تانسور شکل (32,) است، اینها برچسب های مربوط به 32 تصویر هستند.

شما می توانید .numpy() را در هر یک از این تانسورها فراخوانی کنید تا آنها را به numpy.ndarray تبدیل کنید.

داده ها را استاندارد کنید

مقادیر کانال RGB در محدوده [0, 255] است. این برای یک شبکه عصبی ایده آل نیست. به طور کلی باید به دنبال کوچک کردن مقادیر ورودی خود باشید.

در اینجا، با استفاده از tf.keras.layers.Rescaling ، مقادیر را در محدوده [0, 1] استاندارد می‌کنید:

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

دو روش برای استفاده از این لایه وجود دارد. با فراخوانی Dataset.map می توانید آن را به مجموعه داده اعمال کنید:

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 pixel values are now in `[0,1]`.
print(np.min(first_image), np.max(first_image))
0.0 0.96902645

یا، می توانید لایه را در داخل تعریف مدل خود قرار دهید تا استقرار را ساده کنید. در اینجا از روش دوم استفاده خواهید کرد.

مجموعه داده را برای عملکرد پیکربندی کنید

بیایید مطمئن شویم که از واکشی اولیه بافر استفاده می کنیم تا بتوانید بدون مسدود شدن ورودی/خروجی، داده ها را از دیسک به دست آورید. این دو روش مهم هستند که باید هنگام بارگیری داده ها از آنها استفاده کنید:

  • Dataset.cache تصاویر را پس از بارگیری از دیسک در اولین دوره در حافظه نگه می دارد. این اطمینان حاصل می کند که مجموعه داده در حین آموزش مدل شما به یک گلوگاه تبدیل نمی شود. اگر مجموعه داده شما بیش از حد بزرگ است که نمی تواند در حافظه قرار بگیرد، می توانید از این روش برای ایجاد یک حافظه کش عملکردی روی دیسک نیز استفاده کنید.
  • Dataset.prefetch با پیش پردازش داده ها و اجرای مدل در حین آموزش همپوشانی دارد.

خوانندگان علاقه مند می توانند با راهنمای tf.data API اطلاعات بیشتری در مورد هر دو روش و همچنین نحوه کش کردن داده ها در دیسک در بخش Prefetching از عملکرد بهتر کسب کنند.

AUTOTUNE = tf.data.AUTOTUNE

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

یک مدل تربیت کنید

برای کامل بودن، نحوه آموزش یک مدل ساده را با استفاده از مجموعه داده هایی که به تازگی آماده کرده اید نشان خواهید داد.

مدل متوالی از سه بلوک کانولوشن ( tf.keras.layers.Conv2D ) با یک لایه تجمع حداکثر ( tf.keras.layers.MaxPooling2D ) در هر یک از آنها تشکیل شده است. یک لایه کاملاً متصل ( tf.keras.layers.Dense ) با 128 واحد در بالای آن وجود دارد که توسط یک تابع فعال سازی ReLU ( 'relu' ) فعال می شود. این مدل به هیچ وجه تنظیم نشده است - هدف این است که با استفاده از مجموعه داده‌هایی که ایجاد کرده‌اید، مکانیک را به شما نشان دهد. برای کسب اطلاعات بیشتر در مورد طبقه بندی تصاویر، به آموزش طبقه بندی تصاویر مراجعه کنید.

num_classes = 5

model = tf.keras.Sequential([
  tf.keras.layers.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)
])

تابع از دست دادن tf.keras.optimizers.Adam و tf.keras.losses.SparseCategoricalCrossentropy را انتخاب کنید. برای مشاهده دقت آموزش و اعتبارسنجی برای هر دوره آموزشی، آرگومان metrics را به Model.compile کنید.

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 [==============================] - 4s 21ms/step - loss: 1.3091 - accuracy: 0.4281 - val_loss: 1.0982 - val_accuracy: 0.5599
Epoch 2/3
92/92 [==============================] - 1s 12ms/step - loss: 1.0196 - accuracy: 0.5879 - val_loss: 0.9572 - val_accuracy: 0.6213
Epoch 3/3
92/92 [==============================] - 1s 12ms/step - loss: 0.8455 - accuracy: 0.6775 - val_loss: 0.8839 - val_accuracy: 0.6512
<keras.callbacks.History at 0x7ff10c168850>

ممکن است متوجه شوید که دقت اعتبارسنجی در مقایسه با دقت آموزشی پایین است، که نشان می‌دهد مدل شما بیش از حد مناسب است. در این آموزش می‌توانید در مورد اضافه کردن و نحوه کاهش آن بیشتر بدانید.

استفاده از tf.data برای کنترل دقیق تر

ابزار پیش پردازش Keras فوق — tf.keras.utils.image_dataset_from_directory — راهی مناسب برای ایجاد 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/roses/14267691818_301aceda07.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/daisy/2641151167_3bf1349606_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/6495554833_86eb8faa8e_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/4578030672_e6aefd45af.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/144686365_d7e96941ee_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.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:  1

پیکربندی مجموعه داده برای عملکرد

برای آموزش یک مدل با این مجموعه داده، داده های زیر را می خواهید:

  • خوب به هم ریخته شدن.
  • دسته بندی شود.
  • دسته ها در اسرع وقت در دسترس قرار می گیرند.

این ویژگی ها را می توان با استفاده از 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")
2022-01-26 06:29:45.209901: 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

به آموزش مدل ادامه دهید

شما اکنون به صورت دستی یک tf.data.Dataset مشابه با مجموعه ایجاد شده توسط tf.keras.utils.image_dataset_from_directory بالا ساخته اید. می توانید آموزش مدل را با آن ادامه دهید. مانند قبل، فقط برای چند دوره تمرین خواهید کرد تا زمان اجرا را کوتاه نگه دارید.

model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)
Epoch 1/3
92/92 [==============================] - 3s 21ms/step - loss: 0.7305 - accuracy: 0.7245 - val_loss: 0.7311 - val_accuracy: 0.7139
Epoch 2/3
92/92 [==============================] - 1s 13ms/step - loss: 0.5279 - accuracy: 0.8069 - val_loss: 0.7021 - val_accuracy: 0.7316
Epoch 3/3
92/92 [==============================] - 1s 13ms/step - loss: 0.3739 - accuracy: 0.8644 - val_loss: 0.8266 - val_accuracy: 0.6948
<keras.callbacks.History at 0x7ff0ee071f10>

استفاده از مجموعه داده های TensorFlow

تا کنون، این آموزش بر روی بارگذاری اطلاعات از روی دیسک متمرکز شده است. همچنین می‌توانید با کاوش در کاتالوگ بزرگ مجموعه‌های داده با دانلود آسان در TensorFlow Datasets ، یک مجموعه داده برای استفاده پیدا کنید.

همانطور که قبلاً مجموعه داده Flowers را از دیسک بارگیری کرده اید، اکنون آن را با TensorFlow Datasets وارد می کنیم.

مجموعه داده 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 06:29:54.281352: 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

مانند قبل، به یاد داشته باشید که مجموعه‌های آموزشی، اعتبارسنجی و تست را برای عملکرد دسته‌بندی، مخلوط کردن و پیکربندی کنید:

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

با مراجعه به آموزش افزایش داده ها می توانید یک نمونه کامل از کار با مجموعه داده Flowers و TensorFlow Datasets را بیابید.

مراحل بعدی

این آموزش دو راه برای بارگذاری تصاویر از روی دیسک را نشان می دهد. ابتدا یاد گرفتید که چگونه یک مجموعه داده تصویر را با استفاده از لایه ها و ابزارهای پیش پردازش Keras بارگیری و پیش پردازش کنید. سپس، نحوه نوشتن خط لوله ورودی را از ابتدا با استفاده از tf.data . در نهایت، نحوه دانلود مجموعه داده از TensorFlow Datasets را یاد گرفتید.

برای مراحل بعدی شما: