Image Classification Using Python
Hi.. Data Entusiast !
Kali ini kita akan belajar mengenai Image Classification menggunakan program python. Image Classification adalah klasifikasi citra dengan mengelompokkan objek berdasarkan kelas tertentu sehingga kita dapat dengan mudah mengenali objek. Dalam image classification ini dilakukan dengan mengelompokkan jenis bunga yang ada di Indonesia yang terdapat beberapa jenis bunga diantaranya adalah dandelion, rose, sunflower, dan tulip.
Dilakukan analisis klasifikasi gambar dikarena adanya keanekaragaman hayati di Indonesia yang tercatat sebanyak 19.232, sehingga apabila ingin mengetahui jenis keragaman tersebut membutuhkan banyak waktu dan perlu pembelajaran khusus, maka perlu dilakukan analisis klasifikasi gambar untuk mempermudah manusia dalam melakukan pengelompokan keanekaragamn tersebut.
Data yang digunakan dalam klasifikasi gambar kali ini berasal dari https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz
Metode yang digunakan dalam klasifikasi gambar ini adalah CNN (Convolutional Neural Network). CNN adalah salah satu metode algoritma deep learning yang mengimplementasikan jaringan saraf tiruan pada makhluk hidup. Terdapat 2 tahapan yang digunakan pada CNN diantaranya fitur ekstraksi dan klasifikasi. Pada fitur ekstraksi terdapat proses konvolusi dan pooling, sedangkan pada klasifikasi terdapat proses flatten, hidden layer, dan output layer.
Pada tutorial ini menunjukkan klasifikasi gambar bunga menggunakan model tf.keras.squential dan memuat data menggunakan tf.keras.utils.image_dataset_from_directory. Berikut langkah-langkah yang harus dilakukan :
- Memeriksa dan memahami data
- Membangun masukan pipeline
- Membangun model
- Train and test model
Import Tensorflow dan modul lain yang dibutuhkan
import matplotlib.pyplot as plt
import numpy as np
import PIL
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
Download dan eksplor dataset
Data set terdiri atas 3700 gambar bunga yang mengandung 5 sub kategori diantaranya
flower_photo/
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('flower_photos', origin=dataset_url, untar=True)
data_dir = pathlib.Path(data_dir)
Setelah mengunduh, kita memiliki salinan kumpulan data yang tersedia sebanyak 3670 gambar
image_count = len(list(data_dir.glob('*/*.jpg')))
print(image_count)
3670
kita juga dapat melihat gambar beberapa bunga yang ada di dalam dataset dengan menggunakan perintah berikut :
roses = list(data_dir.glob('roses/*'))
PIL.Image.open(str(roses[0]))
maka akan menghasilkan gambar rose dengan kode 0 yaitu sebagai berikut
kita juga dapat melihat bunga tulip dengan menggunakan kode berikut ini
tulips = list(data_dir.glob('tulips/*'))
PIL.Image.open(str(tulips[0]))
maka akan menghasilkan gambar sebagai berikut :
Load data menggunakan Keras Utility
Langkah ini akan membawa kita dari direktori gambar ke disk tf.data.dataset yang hanya dalam beberapa baris kode. Namun sebelumnya kita harus menyamakan ukuran gambar yang akan diletakkan pada direktori baru dengan menggunakan perintah untuk mendefinisikan parameter yang digunakan berikut :
batch_size = 32
img_height = 180
img_width = 180
Kemudian bagi data menjadi data train, test, dan data validasi. Pada praktik kali ini kita akan membagi data menjadi 80% untuk data train dan 20% untuk data test dan validasi dengan menggunakan perintah sebagai berikut.
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)
maka akan didapatkan hasil sebagai berikut untuk data train
Found 3670 files belonging to 5 classes.
Using 2936 files for training.
kemudian perintah berikut digunakan untuk mendapatkan data validasi
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)
maka akan menghasilkan data validasi sebagai berikut
Found 3670 files belonging to 5 classes.
Using 734 files for validation.
Visualisasi data
disini kita dapat melihat sembilan gambar pertama dari dataset training
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")
setelah mengetahui data train, selanjutnya data tersebut akan kita gunakan untuk membuat model dengan menggunakan perintah sebagai berikut :
for image_batch, labels_batch in train_ds:
print(image_batch.shape)
print(labels_batch.shape)
break
maka akan menghasilkan output sebagai berikut :
(32, 180, 180, 3)
(32,)
image_batch adalah tensor berbentuk (32,180,180,3) adalah kumpulan 32 gambar bentuk 180x180x3 (dimensi terakhor mengacu pada saluran warna RGB). Label_batch adalah tensor bentuk (32) adalah yang sesuai dengan 32 gambar.
Konfigurasikan dataset untuk performance
Pastikan untuk menggunakan buffered prefetching, sehingga kita dapat menghasilkan data dari disk tanpa memblokir. Ada 2 metode penting yang harus digunakan saat memuat data diantaranya yaitu :
- dataset.cache menyimpan gambar di memori setelah dimuat dari disk. Ini memastikan set data tidak menjadi hambatan saat melatih model. Jika dataset terlalu besar untuk masuk ke dalam memori, maka kita dapat menggunakan metode ini untuk membuat cache ondisk yang berkinerja baik
- dataset.prefetch tumpang tindih dengan prapemrosesan data dan eksekusi model saat training.
AUTOTUNE = tf.data.AUTOTUNE
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
Standarisasi data
RGB channels berada pada rentang [0,255] angka tersebut tidak ideal untuk jaringan saraf, secara umum kita harus berusaha membuat nilai input yang kecil maka kita akan membakukan nilainya dalam rentang [0,1] dengan menggunakan tf.keras.layers.Rescaling :
normalization_layer = layers.Rescaling(1./255)
ada 2 cara dalam menggunakan layer ini, kamu dapat menggunakannya untuk 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))
Membuat Model
Model keras squential terdiri dari tiga blok konvolusi (tf.keras.layers.Conv2D) dengan max pooling layers (tf.keras.layers.MaxPooling2D) dimasing-masingnya. Ada lapisan yang terhubung sepenuhnya (tf.keras.layers.Dense) dengan 128 unit di atasnya yang diaktifkan oleh fungsi aktivasi ReLU.
num_classes = len(class_names)
model = Sequential([
layers.Rescaling(1./255, input_shape=(img_height, img_width, 3)),
layers.Conv2D(16, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(32, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(64, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dense(num_classes)
])
dalam praktik ini kita memilih tf.keras.optimizers.Adam optimizer dan tf.keras.losses.SparseCategoricalCrossentropy loss function untuk melihat akurasi training dan validasi untuk setiap periode training, kemudian diteruskan ke model.compile
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
kemudian untuk melihat semua layers maka dapat menggunakan model.summary :
model.summary()
Output exceeds the size limit. Open the full output data in a text editor
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
rescaling_1 (Rescaling) (None, 180, 180, 3) 0
conv2d (Conv2D) (None, 180, 180, 16) 448
max_pooling2d (MaxPooling2D (None, 90, 90, 16) 0
)
conv2d_1 (Conv2D) (None, 90, 90, 32) 4640
max_pooling2d_1 (MaxPooling (None, 45, 45, 32) 0
2D)
conv2d_2 (Conv2D) (None, 45, 45, 64) 18496
max_pooling2d_2 (MaxPooling (None, 22, 22, 64) 0
2D)
flatten (Flatten) (None, 30976) 0
dense (Dense) (None, 128) 3965056
...
Total params: 3,989,285
Trainable params: 3,989,285
Non-trainable params: 0
_________________________________________________________________
Train Model
Melatih model untuk epochs 10 dengan metode keras model.fit :
epochs=10
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs
)
Epoch 1/10
92/92 [==============================] - 59s 576ms/step - loss: 1.4040 - accuracy: 0.4060 - val_loss: 1.1041 - val_accuracy: 0.5327
Epoch 2/10
92/92 [==============================] - 68s 736ms/step - loss: 1.0053 - accuracy: 0.6035 - val_loss: 0.9673 - val_accuracy: 0.5872
Epoch 3/10
92/92 [==============================] - 68s 737ms/step - loss: 0.8111 - accuracy: 0.6948 - val_loss: 0.9875 - val_accuracy: 0.6213
Epoch 4/10
92/92 [==============================] - 68s 741ms/step - loss: 0.6102 - accuracy: 0.7766 - val_loss: 1.0433 - val_accuracy: 0.6076
Epoch 5/10
92/92 [==============================] - 68s 740ms/step - loss: 0.4545 - accuracy: 0.8294 - val_loss: 0.9995 - val_accuracy: 0.6608
Epoch 6/10
92/92 [==============================] - 68s 740ms/step - loss: 0.2804 - accuracy: 0.9097 - val_loss: 1.4863 - val_accuracy: 0.5926
Epoch 7/10
92/92 [==============================] - 69s 746ms/step - loss: 0.1967 - accuracy: 0.9295 - val_loss: 1.4659 - val_accuracy: 0.6035
Epoch 8/10
92/92 [==============================] - 68s 741ms/step - loss: 0.1242 - accuracy: 0.9649 - val_loss: 1.5598 - val_accuracy: 0.6185
Epoch 9/10
92/92 [==============================] - 68s 740ms/step - loss: 0.0535 - accuracy: 0.9864 - val_loss: 1.7331 - val_accuracy: 0.6417
Epoch 10/10
92/92 [==============================] - 68s 741ms/step - loss: 0.0245 - accuracy: 0.9946 - val_loss: 1.8592 - val_accuracy: 0.6444
Visualisasi Hasil
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs_range = range(epochs)
plt.figure(figsize=(8, 8))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()