Bantuan melindungi Great Barrier Reef dengan TensorFlow pada Kaggle Bergabung Tantangan

Muat dan praproses gambar

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

Tutorial ini menunjukkan cara memuat dan melakukan praproses dataset gambar dalam tiga cara:

Mempersiapkan

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

Unduh kumpulan data bunga

Tutorial ini menggunakan kumpulan data beberapa ribu foto bunga. Dataset bunga berisi lima 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), Anda sekarang harus memiliki salinan foto bunga yang tersedia. Ada 3.670 total gambar:

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

Setiap direktori berisi gambar dari jenis bunga tersebut. Berikut beberapa bunga 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

Muat data menggunakan utilitas Keras

Beban Mari gambar-gambar ini dari disk menggunakan membantu tf.keras.utils.image_dataset_from_directory utilitas.

Buat kumpulan data

Tentukan beberapa parameter untuk loader:

batch_size = 32
img_height = 180
img_width = 180

Ini adalah praktik yang baik untuk menggunakan pemisahan validasi saat mengembangkan model Anda. Anda akan menggunakan 80% gambar untuk pelatihan dan 20% untuk validasi.

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.

Anda dapat menemukan nama-nama kelas di class_names atribut pada dataset ini.

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

Visualisasikan datanya

Berikut adalah sembilan 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 melewati mereka untuk model.fit (ditunjukkan kemudian dalam tutorial ini). Jika Anda suka, Anda juga dapat secara manual mengulangi kumpulan 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,)

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

Anda dapat menghubungi .numpy() pada salah satu dari tensor ini untuk mengkonversikannya ke numpy.ndarray .

Standarisasi data

Nilai-nilai channel RGB berada di [0, 255] jangkauan. Ini tidak ideal untuk jaringan saraf; secara umum Anda harus berusaha membuat nilai input Anda kecil.

Di sini, Anda akan standarisasi nilai-nilai berada di [0, 1] kisaran dengan menggunakan tf.keras.layers.Rescaling :

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

Ada dua cara untuk menggunakan lapisan ini. Anda dapat menerapkannya ke dataset dengan memanggil 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

Atau, Anda dapat menyertakan lapisan di dalam definisi model Anda untuk menyederhanakan penerapan. Anda akan menggunakan pendekatan kedua di sini.

Konfigurasikan kumpulan data untuk kinerja

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

  • Dataset.cache membuat gambar dalam memori setelah mereka dimuat dari disk selama zaman pertama. Ini akan memastikan kumpulan data tidak menjadi hambatan saat melatih model Anda. Jika kumpulan data Anda terlalu besar untuk dimasukkan ke dalam memori, Anda juga dapat menggunakan metode ini untuk membuat cache di disk yang berkinerja baik.
  • Dataset.prefetch tumpang tindih Data preprocessing dan pelaksanaan model yang saat pelatihan.

Pembaca yang tertarik dapat mempelajari lebih lanjut tentang kedua metode, serta bagaimana cache data ke disk di bagian Prefetching dari kinerja yang lebih baik dengan tf.data API panduan.

AUTOTUNE = tf.data.AUTOTUNE

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

Latih seorang model

Untuk kelengkapan, Anda akan menunjukkan cara melatih model sederhana menggunakan kumpulan data yang baru saja Anda siapkan.

The Sequential Model terdiri dari tiga blok lilit ( tf.keras.layers.Conv2D ) dengan lapisan pooling max ( tf.keras.layers.MaxPooling2D ) di masing-masing. Ada lapisan sepenuhnya terhubung ( tf.keras.layers.Dense ) dengan 128 unit di atasnya yang diaktifkan oleh ReLU fungsi aktivasi ( 'relu' ). Model ini belum disetel dengan cara apa pun—tujuannya adalah untuk menunjukkan kepada Anda mekanisme menggunakan kumpulan data yang baru saja Anda buat. Untuk mempelajari lebih lanjut tentang klasifikasi citra, kunjungi klasifikasi Gambar tutorial.

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

Pilih tf.keras.optimizers.Adam optimizer dan tf.keras.losses.SparseCategoricalCrossentropy fungsi kerugian. Untuk tampilan pelatihan dan akurasi validasi untuk setiap zaman pelatihan, lulus metrics argumen untuk 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.2935 - accuracy: 0.4588 - val_loss: 1.1072 - val_accuracy: 0.5463
Epoch 2/3
92/92 [==============================] - 1s 11ms/step - loss: 1.0370 - accuracy: 0.5834 - val_loss: 0.9830 - val_accuracy: 0.6226
Epoch 3/3
92/92 [==============================] - 1s 11ms/step - loss: 0.8740 - accuracy: 0.6689 - val_loss: 0.9003 - val_accuracy: 0.6676
<keras.callbacks.History at 0x7f44180b31d0>

Anda mungkin melihat akurasi validasi rendah dibandingkan dengan akurasi pelatihan, yang menunjukkan model Anda terlalu pas. Anda dapat mempelajari lebih lanjut tentang overfitting dan bagaimana untuk mengurangi itu dalam tutorial .

Menggunakan tf.data untuk kontrol yang lebih baik

Di atas Keras preprocessing utilitas yang tf.keras.utils.image_dataset_from_directory -is cara mudah untuk membuat tf.data.Dataset dari direktori gambar.

Untuk kontrol butiran halus, Anda dapat menulis pipa masukan Anda sendiri menggunakan tf.data . Bagian ini menunjukkan bagaimana melakukan hal itu, dimulai dengan jalur file dari file TGZ yang Anda 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/tulips/16055807744_000bc07afc_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/daisy/14399435971_ea5868c792.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/13509973805_bda5fa8982.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/6994925894_030e157fe0.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/4890268276_563f40a193.jpg'

Struktur pohon dari file dapat digunakan untuk menyusun class_names daftar.

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 set data menjadi set pelatihan 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 mencetak panjang setiap kumpulan data sebagai berikut:

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

Menulis fungsi pendek yang mengubah path file ke (img, label) pasangan:

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

Gunakan Dataset.map untuk membuat dataset dari image, label pasangan:

# 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 kumpulan data untuk kinerja

Untuk melatih model dengan kumpulan data ini, Anda akan menginginkan data:

  • Untuk dikocok dengan baik.
  • Untuk di-batch.
  • Batch akan tersedia sesegera mungkin.

Fitur-fitur ini dapat ditambahkan dengan menggunakan tf.data API. Untuk lebih jelasnya, kunjungi Masukan Pipeline Kinerja panduan.

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 datanya

Anda dapat memvisualisasikan kumpulan data ini mirip 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")
2021-10-26 01:32:12.160250: 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

Lanjutkan melatih model

Anda telah sekarang secara manual membangun mirip tf.data.Dataset dengan yang diciptakan oleh tf.keras.utils.image_dataset_from_directory di atas. Anda dapat melanjutkan melatih model dengannya. Seperti sebelumnya, Anda akan berlatih hanya beberapa epoch untuk mempersingkat waktu lari.

model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)
Epoch 1/3
92/92 [==============================] - 2s 20ms/step - loss: 0.7521 - accuracy: 0.7183 - val_loss: 0.6710 - val_accuracy: 0.7452
Epoch 2/3
92/92 [==============================] - 1s 12ms/step - loss: 0.5771 - accuracy: 0.7861 - val_loss: 0.7169 - val_accuracy: 0.7221
Epoch 3/3
92/92 [==============================] - 1s 12ms/step - loss: 0.3940 - accuracy: 0.8542 - val_loss: 0.7691 - val_accuracy: 0.7180
<keras.callbacks.History at 0x7f437822c710>

Menggunakan Kumpulan Data TensorFlow

Sejauh ini, tutorial ini berfokus pada memuat data dari disk. Anda juga dapat menemukan dataset untuk digunakan dengan menjelajahi besar katalog mudah untuk unduh dataset di TensorFlow Datasets .

Karena sebelumnya Anda telah memuat set data Flowers dari disk, sekarang mari impor dengan TensorFlow Datasets.

Download Bunga dataset menggunakan 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,
)

Dataset bunga memiliki lima kelas:

num_classes = metadata.features['label'].num_classes
print(num_classes)
5

Ambil gambar dari kumpulan data:

get_label_name = metadata.features['label'].int2str

image, label = next(iter(train_ds))
_ = plt.imshow(image)
_ = plt.title(get_label_name(label))
2021-10-26 01:32:22.877036: 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

Seperti sebelumnya, ingatlah untuk mengelompokkan, mengacak, dan mengonfigurasi set pelatihan, validasi, dan pengujian untuk kinerja:

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

Anda dapat menemukan contoh lengkap bekerja dengan dataset Bunga dan TensorFlow dataset dengan mengunjungi data augmentation tutorial.

Langkah selanjutnya

Tutorial ini menunjukkan dua cara memuat gambar dari disk. Pertama, Anda mempelajari cara memuat dan melakukan praproses kumpulan data gambar menggunakan lapisan dan utilitas prapemrosesan Keras. Berikutnya, Anda belajar bagaimana menulis sebuah pipa masukan dari awal dengan menggunakan tf.data . Terakhir, Anda telah mempelajari cara mendownload set data dari TensorFlow Datasets.

Untuk langkah Anda selanjutnya: