Halaman ini diterjemahkan oleh Cloud Translation API.
Switch to English

Memuat gambar

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub Unduh buku catatan

Tutorial ini menunjukkan cara memuat dan memproses dataset gambar dengan dua cara. Pertama, Anda akan menggunakan utilitas dan lapisan preprocessing Keras tingkat tinggi. Selanjutnya, Anda akan menulis pipa input Anda sendiri dari awal menggunakan tf.data .

Mempersiapkan

 import numpy as np
import os
import PIL
import PIL.Image
import tensorflow as tf
 
 print(tf.__version__)
 
2.3.0

Unduh dataset bunga

Tutorial ini menggunakan dataset beberapa ribu foto bunga. Kumpulan bunga berisi 5 sub-direktori, satu per kelas:

 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)
 

Setelah mengunduh (218MB), sekarang Anda harus memiliki salinan foto bunga yang tersedia. Ada 3670 total gambar:

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

Setiap direktori berisi gambar jenis bunga itu. Berikut ini beberapa mawar:

 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

Load menggunakan hard.preprocessing

Mari kita memuat gambar-gambar ini dari disk menggunakan image_dataset_from_directory .

Buat dataset

Tentukan beberapa parameter untuk pemuat:

 batch_size = 32
img_height = 180
img_width = 180
 

Merupakan praktik yang baik untuk menggunakan pemisahan validasi saat mengembangkan model Anda. Kami akan menggunakan 80% dari gambar untuk pelatihan, dan 20% untuk validasi.

 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.

Anda dapat menemukan nama kelas di atribut class_names pada kumpulan data ini.

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

Visualisasikan data

Berikut adalah 9 gambar pertama dari dataset pelatihan.

 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

Anda dapat melatih model menggunakan dataset ini dengan mengirimkannya ke model.fit (ditampilkan nanti dalam tutorial ini). Jika suka, Anda juga dapat secara manual mengulangi set data dan mengambil kumpulan gambar:

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

image_batch adalah tensor bentuk (32, 180, 180, 3) . Ini adalah kumpulan 32 gambar bentuk 180x180x3 (dimensi terakhir mengacu pada saluran warna RGB). label_batch adalah tensor bentuk (32,) , ini adalah label yang sesuai dengan 32 gambar.

Membakukan data

Nilai-nilai saluran RGB berada dalam kisaran [0, 255] . Ini tidak ideal untuk jaringan saraf; secara umum Anda harus berusaha membuat nilai input Anda kecil. Di sini, kita akan menstandarkan nilai ke dalam [0, 1] dengan menggunakan layer Penskalaan Ulang.

 from tensorflow.keras import layers

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

Ada dua cara untuk menggunakan lapisan ini. Anda dapat menerapkannya pada dataset dengan memanggil peta:

 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

Atau, Anda dapat memasukkan lapisan di dalam definisi model Anda untuk menyederhanakan penempatan. Kami akan menggunakan pendekatan kedua di sini.

Konfigurasikan dataset untuk kinerja

Mari kita pastikan untuk menggunakan prefetching buffered sehingga kita dapat menghasilkan data dari disk tanpa I / O menjadi memblokir. Ini adalah dua metode penting yang harus Anda gunakan saat memuat data.

.cache() menyimpan gambar dalam memori setelah mereka dimuat dari disk selama zaman pertama. Ini akan memastikan dataset tidak menjadi hambatan saat melatih model Anda. Jika dataset Anda terlalu besar untuk dimasukkan ke dalam memori, Anda juga dapat menggunakan metode ini untuk membuat cache di-performan.

.prefetch() tumpang tindih preprocessing data dan eksekusi model saat pelatihan.

Pembaca yang tertarik dapat mempelajari lebih lanjut tentang kedua metode ini, serta cara menyimpan data ke disk dalam panduan kinerja data .

 AUTOTUNE = tf.data.experimental.AUTOTUNE

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

Latih model

Untuk kelengkapan, kami akan menunjukkan cara melatih model sederhana menggunakan set data yang baru saja kami siapkan. Model ini belum disetel dengan cara apa pun - tujuannya adalah untuk menunjukkan kepada Anda mekanisme menggunakan set data yang baru saja Anda buat. Untuk mempelajari lebih lanjut tentang klasifikasi gambar, kunjungi tutorial ini.

 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 [==============================] - 6s 66ms/step - loss: 1.3282 - accuracy: 0.4240 - val_loss: 1.1035 - val_accuracy: 0.5804
Epoch 2/3
92/92 [==============================] - 1s 11ms/step - loss: 1.0304 - accuracy: 0.5913 - val_loss: 0.9515 - val_accuracy: 0.6267
Epoch 3/3
92/92 [==============================] - 1s 11ms/step - loss: 0.8712 - accuracy: 0.6689 - val_loss: 0.9268 - val_accuracy: 0.6471

<tensorflow.python.keras.callbacks.History at 0x7f86d80ad128>

Anda mungkin memperhatikan keakuratan validasinya rendah dibandingkan dengan keakuratan pelatihan, menunjukkan bahwa model kami terlalu sesuai. Anda dapat mempelajari lebih lanjut tentang overfitting dan cara menguranginya dalam tutorial ini.

Menggunakan tf.data untuk kontrol yang lebih baik

Utilitas pemrosesan.proses keras di atas adalah cara mudah untuk membuat tf.data.Dataset dari direktori gambar. Untuk kontrol butir yang lebih halus, Anda dapat menulis pipa input Anda sendiri menggunakan tf.data . Bagian ini menunjukkan bagaimana melakukan hal itu, dimulai dengan jalur file dari zip yang telah kita unduh sebelumnya.

 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/1445228333_59a07e0801.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/14128835667_b6a916222c.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/7551637034_55ae047756_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/4574736702_b15ecf97d0_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/6867597533_d65d1c39fb_n.jpg'

Struktur pohon dari file dapat digunakan untuk mengkompilasi daftar 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']

Pisahkan dataset menjadi kereta dan validasi:

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

Anda dapat melihat panjang setiap dataset sebagai berikut:

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

Tulis fungsi singkat yang mengubah jalur file ke pasangan (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
 

Gunakan Dataset.map untuk membuat dataset image, label pasang 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

Konfigurasikan dataset untuk kinerja

Untuk melatih model dengan dataset ini, Anda akan menginginkan datanya:

  • Untuk dikocok dengan baik.
  • Untuk dikelompokkan.
  • Batch akan tersedia sesegera mungkin.

Fitur-fitur ini dapat ditambahkan menggunakan API tf.data . Untuk detail lebih lanjut, lihat panduan Kinerja Pipa Input .

 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)
 

Visualisasikan data

Anda dapat memvisualisasikan set data ini dengan yang Anda buat sebelumnya.

 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

Lanjutkan melatih model

Anda sekarang telah secara manual membuat tf.data.Dataset mirip dengan yang dibuat oleh keras.preprocessing atas. Anda dapat melanjutkan pelatihan model dengan itu. Seperti sebelumnya, kita akan berlatih hanya untuk beberapa zaman untuk menjaga waktu berjalan yang singkat.

 model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)
 
Epoch 1/3
92/92 [==============================] - 2s 19ms/step - loss: 0.7267 - accuracy: 0.7272 - val_loss: 0.7963 - val_accuracy: 0.7098
Epoch 2/3
92/92 [==============================] - 1s 11ms/step - loss: 0.5384 - accuracy: 0.7987 - val_loss: 0.8067 - val_accuracy: 0.6894
Epoch 3/3
92/92 [==============================] - 1s 11ms/step - loss: 0.3382 - accuracy: 0.8770 - val_loss: 1.0317 - val_accuracy: 0.6662

<tensorflow.python.keras.callbacks.History at 0x7f87cd496320>

Langkah selanjutnya

Tutorial ini menunjukkan dua cara memuat gambar dari disk. Pertama, Anda belajar cara memuat dan memproses dataset gambar menggunakan lapisan dan utilitas preprocessing Keras. Selanjutnya, Anda belajar cara menulis pipa input dari awal menggunakan tf.data. Sebagai langkah selanjutnya, Anda dapat mempelajari cara menambahkan augmentasi data dengan mengunjungi tutorial ini. Untuk mempelajari lebih lanjut tentang tf.data, Anda dapat mengunjungi panduan ini.