Pengenalan Jenis Bunga Menggunakan CNN

Muchamad Nur Kholis
10 min readJan 5, 2023

--

Image Classification Series
Part I
: Mengenal Convolutional Neural Network (CNN)
Part II: Pengenalan Jenis Bunga Menggunakan CNN
Part III: Mengenal Pre-trained Model CNN

Pada part sebelumnya, kita telah mempelajari konsep dasar CNN. Nah di Part II ini kita membahas penerapan CNN yaitu Pengenalan Jenis Bunga. Dalam hal ini akan digunakan Python. Berikut disediakan Kaggle Notebook yang saya gunakan pada project kali ini [link].

Deskripsi Project

Project kali ini yaitu pengenalan jenis bunga menggunakan CNN. Dalam hal ini akan digunakan dataset Kaggle yang dapat diunduh melalui link berikut: [link]. Data ini dikumpulkan dengan cara scraping melalui website flickr, google images, dan yandex images. Dataset ini berisi 4317 gambar bunga yang terdiri dari 5 kelas yaitu bunga daisy, dandelion, rose, sunflower, dan tulip. Tujuan dari project kali ini adalah untuk mengenali dan memprediksi jenis bunga tersebut dengan menggunakan CNN. Dengan pengenalan bunga ini, kita dapat mengenali bunga yang jumlahnya banyak hingga ribuan bahkan jutaan secara otomatis menggunakan computer vision sehingga proses pengenalan akan menjadi lebih cepat dan efisien daripada jika melakukan proses pengenalan secara manual.

Metodologi

Metode yang digunakan yaitu CNN, metode ini sering digunakan dalam masalah klasifikasi gambar. Kelebihan dari metode CNN ini adalah dapat secara otomatis mengekstraksi ciri penting dari setiap citra tanpa bantuan manusia, selain itu metode CNN juga lebih efisien dibandingkan metode neural network lainnya terutama untuk memori dan kompleksitas

Pada proses training, data akan dibagi ke dalam data train dan data test dengan proporsi 80%:20%. Data train digunakan untuk pembangunan model sedangkan data test digunakan untuk validasi model.

Proses training dilakukan dengan melakukan hyperparameter optimization dimana penulis akan mecoba beberapa skema yang mengkombinasikan ukuran input gambar (100,150), optimizer (RMSProp dan Adam), dan jumlah neuron pada Dense layer (256,512). Proses training ini dilakukan dengan jumlah batch size yaitu 128 dan steps per epoch sebanyak 26 dengan epoch sebanyak 50. Dari hasil training ini, hyperparameter yang memberikan akurasi terbaik yaitu input gambar 150x150 pixel, optimizer Adam, dan jumah neuron pada Dense layer sebanyak 512 neuron. Dalam hal ini, ukuran performa model yang digunakan yaitu categorical crossentopry loss dan accuracy.

Flower Recognition

Pertama-tama, impor package yang dibutuhkan untuk impor data serta menampilkan data dalam.

import os
from tqdm import tqdm
import numpy as np
import pandas as pd
import random
from random import shuffle
import cv2
from PIL import Image
import matplotlib.pyplot as plt
import seaborn as sns
# Ignore the warnings
import warnings
warnings.filterwarnings('always')
warnings.filterwarnings('ignore')

Lalu, untuk melihat jenis bunga yang terdapat pada data gunakan syntax berikut

import os
print(os.listdir('/kaggle/input/flowers-recognition/flowers'))

Maka akan terlihat jenis bunga yang ada pada data yaitu seperti berikut.

Impor Data

Data ini berisikan gambar-gambar yang telah dikelompokkan dalam 5 folder. 1 folder mewakili 1 jenis bunga. Lebih jelasnya, perhatikan gambar berikut.

Folder daisy semuanya berisi gambar bunga daisy, begitu juga dengan folder lain.

Dalam hal ini proses impor akan dilakukan dengan cara mengimpor 1 folder dan berikan label pada seluruh gambar di folder tersebut, lalu ulangi untuk folder lainnya. Pada proses impor ini, semua gambar juga akan diubah ke dalam ukuran yang sama yaitu 150x150 pixel. Berikut ini syntax untuk mengimpor data beserta labelnya.

X=[]
L=[]
IMG_SIZE = 150
DAISY = '/kaggle/input/flowers-recognition/flowers/daisy'
SUNFLOWER = '/kaggle/input/flowers-recognition/flowers/sunflower'
TULIP = '/kaggle/input/flowers-recognition/flowers/tulip'
DANDELION = '/kaggle/input/flowers-recognition/flowers/dandelion'
ROSE = '/kaggle/input/flowers-recognition/flowers/rose'

def assign_label(img,flower_type):
return flower_type

def make_train_data(flower_type,DIR):
for img in tqdm(os.listdir(DIR)):
label = assign_label(img, flower_type)
path = os.path.join(DIR, img)
img = cv2.imread(path, cv2.IMREAD_COLOR)
img = cv2.resize(img, (IMG_SIZE,IMG_SIZE))

X.append(np.array(img))
L.append(str(label))

Lalu, impor data bunga dengan menggunakan fungsi make_train_data(jenis_bunga,directory) yang telah dibuat sebelumnya.

make_train_data('Daisy',DAISY)
make_train_data('Sunflower',SUNFLOWER)
make_train_data('Tulip',TULIP)
make_train_data('Dandelion',DANDELION)
make_train_data('Rose',ROSE)
print(len(X))

Maka, akan muncul output sebagai berikut.

Terlihat bahwa jumlah data yaitu sebanyak 4317 gambar bunga.

Setelah itu, saya akan mencoba menampilkan data yang telah diimpor dengan mengambil sampel gambar. Syntax yang digunakan sebagai berikut.

fig,ax=plt.subplots(5,2)
fig.set_size_inches(15,15)
for i in range(5):
for j in range (2):
l = random.randint(0,len(L))
ax[i,j].imshow(X[l])
ax[i,j].set_title('Flower: '+L[l])

plt.tight_layout()

Maka akan diperoleh hasil sebagai berikut.

Setelah itu impor package yang dibutuhkan untuk pembuatan model seperti berikut.

import tensorflow as tf

#model selection
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
from sklearn.preprocessing import LabelEncoder

#preprocess.
from keras import backend as K
from keras.preprocessing.image import ImageDataGenerator

# specifically for cnn
from keras.models import Sequential
from keras.layers import Dropout, Flatten,Activation
from keras.layers import Conv2D, MaxPooling2D, BatchNormalization
from keras.layers import Dense
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.utils import to_categorical

Image Pre-processing

Pada tahap ini, akan dilakukan stadarisasi pada data gambar yang awalnya berada di rentang [0,255] akan diubah menjadi [0,1]. Selain itu, akan dilakukan categorical encoding pada label gambar menggunakan metode One-Hot Encoding. Syntax yang digunakan sebagai berikut.

# Standardization
X = np.array(X)
X = X/255
# Categorical encoding
le = LabelEncoder()
Y = le.fit_transform(L)
Y = to_categorical(Y,5)

Train-Test Split

Tahap selanjutnya yaitu membagi data menjadi data train dan data test. Hal ini dilakukan untuk proses validasi model yang diperoleh apakah baik digunakan untuk prediksi data baru. Dalam hal ini saya akan menggunakan perbandingan 80%:20%.

np.random.seed(2023)
random.seed(2023)

X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=42)

print("X_train: ", X_train.shape)
print("X_test: ", X_test.shape)
print("Y_train: ", Y_train.shape)
print("Y_test: ", Y_test.shape)

Maka akan diperoleh hasil sebagai berikut.

Dari gambar di atas dapat diketahui bahwa data yang dilakukan untuk proses training berjumlah 3453 sedangkan data yang digunakan untuk proses validasi berjumlah 864.

Modelling

Langkah selanjutnya yaitu melakukan pemodelan serta membangun arsiteksur CNN. Untuk menampilkan arsitektur CNN gunakan syntax .summary().

Arsitektur yang saya gunakan untuk membuat klasifikasi jenis bunga ini yaitu sebagai berikut:

  1. Input berupa gambar berukuran 150 x 150 pixel
  2. Model yang digunakan yaitu model sequential
  3. Layer pertama yaitu convolutional 2 dimensi dengan jumlah filter sebanyak 32 menggunakan kernel 5 x 5 pixel.
  4. Layer kedua yaitu max pooling dengan ukuran 2 x 2 pixel untuk mereduksi jumlah parameter input yang dihasilkan.
  5. Layer ketiga yaitu convolutional 2 dimensi dengan jumlah filter sebanyak 64 menggunakan kernel 3 x 3pixel.
  6. Layer keempat yaitu max pooling dengan ukuran 2 x 2 pixel untuk mereduksi jumlah parameter input yang dihasilkan.
  7. Layer kelima yaitu convolutional 2 dimensi dengan jumlah filter sebanyak 96 menggunakan kernel 3 x 3 pixel.
  8. Layer keenam yaitu max pooling dengan ukuran 2 x 2 pixel untuk mereduksi jumlah parameter input yang dihasilkan.
  9. Layer ketujuh yaitu convolutional 2 dimensi dengan jumlah filter sebanyak 96 menggunakan kernel 3 x 3 pixel.
  10. Layer kedelapan yaitu max pooling dengan ukuran 2 x 2 pixel untuk mereduksi jumlah parameter input yang dihasilkan.
  11. Layer kesembilan yaitu flatten untuk membuat input yang memiliki banyak dimensi menjadi satu dimensi saja.
  12. Layer kesepuluh yaitu dense yang berisi 512 neuron dengan fungsi aktivasi yaitu relu.
  13. Layer kesebelas yaitu dropout dengan threshold sebesar 0.2.
  14. Layer keduabelas yaitu dense yang berisi 5 neuron dengan fungsi aktivasi yaitu softmax.

Gunakan syntax berikut untuk melakukan pemodelan.

# modelling with CNN algorithm

model = Sequential()

model.add(Conv2D(filters = 32, kernel_size = (5,5), padding = 'Same', activation = 'relu', input_shape = (150,150,3)))
model.add(MaxPooling2D(pool_size = (2,2)))

model.add(Conv2D(filters = 64, kernel_size = (3,3), padding = 'Same', activation = 'relu'))
model.add(MaxPooling2D(pool_size = (2,2), strides = (2,2)))

model.add(Conv2D(filters = 96, kernel_size = (3,3), padding = 'Same', activation = 'relu'))
model.add(MaxPooling2D(pool_size = (2,2), strides = (2,2)))

model.add(Conv2D(filters = 96, kernel_size = (3,3), padding = 'Same', activation = 'relu'))
model.add(MaxPooling2D(pool_size = (2,2), strides = (2,2)))

model.add(Flatten())
model.add(Dense(512, activation = "relu"))
model.add(Dropout(0.2))
model.add(Dense(5, activation = "softmax"))

model.summary()

Maka akan diperoleh hasil sebagai berikut.

Output di atas menunjukkan arsitektur CNN yang telah dibangun yang terdiri dari 12 layer dengan total parameter yaitu 4143749. Detail tipe layer, output layer, serta jumlah parameter juga dapat dilihat dari output di atas.

Lalu, compile model yang telah dibentuk. Dalam hal ini akan digunakan optimizer Adam dengan learning rate sebesar 0.001, categorical cross entropy loss, dan mertics accuracy untuk menentukan tingkat akurasi model karena kelas yang diprediksi terdiri dari 5 kelas bukan biner.

model.compile(optimizer = Adam(lr=0.001), loss = 'categorical_crossentropy', metrics = ['accuracy'])

Setelah itu, mengatur jumlah batch size dan epoch. Selain itu juga mengatur learning rate untuk mereduksi learning rate jika metrik akurasi tidak menunjukkan perkembangan.

batch_size = 128
epochs = 50

from keras.callbacks import ReduceLROnPlateau
red_lr = ReduceLROnPlateau(monitor = 'val_accuracy', patience = 3, verbose = 1, factor = 0.1)

Selanjutnya, melakukan augmentasi gambar untuk mengindari overfitting. Dalam hal ini saya akan melakukan rotasi (putar), shift (geser), serta flip (balik) pada gambar.

datagen = ImageDataGenerator(
featurewise_center = False, # set input mean to 0 over the dataset
samplewise_center = False, # set each sample mean to 0
featurewise_std_normalization = False, # divide inputs by std of the dataset
samplewise_std_normalization = False, # divide each input by its std
zca_whitening = False, # apply ZCA whitening
rotation_range = 10, # randomly rotate images in the range (degrees, 0 to 180)
zoom_range = 0.1, # Randomly zoom image
width_shift_range = 0.2, # randomly shift images horizontally (fraction of total width)
height_shift_range = 0.2, # randomly shift images vertically (fraction of total height)
horizontal_flip = True, # randomly flip images
vertical_flip = False) # randomly flip images

datagen.fit(X_train)

Setelah dibentuk model, lalu dilakukan fitting model. Dalam hal ini akan dilakukan perulangan (epoch) sebanyak 50 kali dan batch size sebanyak 128. Syntax yang digunakan sebagai berikut.

History = model.fit_generator(datagen.flow(X_train, Y_train, batch_size = batch_size),
epochs = epochs, validation_data = (X_test,Y_test),
verbose = 1, steps_per_epoch = X_train.shape[0] // batch_size)

Maka akan diperoleh hasil sebagai berikut.

Performa Model

Untuk mempermudah dalam melihat tingkat akurasi model, buatlah plot dari Training dan Validation Loss serta Accuracy dengan syntax berikut.

# Training and Validation Loss
plt.plot(History.history['loss'])
plt.plot(History.history['val_loss'])
plt.title('Model Loss')
plt.ylabel('Loss')
plt.xlabel('Epochs')
plt.legend(['Train Loss', 'Test Loss'])
plt.show()
# Training and Vaidation Accuracy
plt.plot(History.history['accuracy'])
plt.plot(History.history['val_accuracy'])
plt.title('Model Accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epochs')
plt.legend(['Train Accuracy', 'Test Accuracy'])
plt.show()

Dari hasil tersebut dapat diketahui bahwa tingkat akurasi model cukup bagus. Hal ini dapat dilihat dari training serta validation accuracy yang tinggi (mencapai 82%) dan juga training dan validation loss yang rendah (mencapai 0.5).

Selain itu, tingkat akurasi juga dapat dilihat dari confusion matrix. Berikut ini syntax yang digunakan untuk membuat confusion matrix. Dalam hal ini, saya akan menggunakan data validasi.

# Look at confusion matrix 
from sklearn.metrics import confusion_matrix, accuracy_score
import itertools

def plot_confusion_matrix(cm, classes, normalize = False, title = 'Confusion matrix', cmap = plt.cm.Blues):
plt.imshow(cm, interpolation = 'nearest', cmap = cmap)
plt.title(title)
plt.colorbar()
tick_marks = np.arange(len(classes))
plt.xticks(tick_marks, classes, rotation = 45)
plt.yticks(tick_marks, classes)

if normalize:
cm = cm.astype('float') / cm.sum(axis = 1)[:, np.newaxis]

thresh = cm.max() / 2.
for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
plt.text(j, i, cm[i, j], horizontalalignment = "center",
color = "white" if cm[i, j] > thresh else "black")

plt.tight_layout()
plt.ylabel('True label')
plt.xlabel('Predicted label')

# Predict the values from the validation dataset
Y_pred = model.predict(X_test)
# Convert predictions classes to one hot vectors
Y_pred_classes = np.argmax(Y_pred,axis = 1)
# Convert validation observations to one hot vectors
Y_true = np.argmax(Y_test,axis = 1)
# compute the confusion matrix
confusion_mtx = confusion_matrix(Y_true, Y_pred_classes)
# plot the confusion matrix
plot_confusion_matrix(confusion_mtx, classes = range(5))
# accuracy
print("Accuracy : ", accuracy_score(Y_true, Y_pred_classes))

Maka akan diperoleh hasil sebagai berikut:

Dari confusion matrix di atas, x-axis merupakan data prediksi sedangkan y-axis merupakan data aktual. Sehingga, prediksi benar berada pada diagonal confusion matrix tersebut. Dari hasil tersebut diketahui bahwa tingkat akurasi model untuk memprediksi data validasi yaitu sebesar 82,29%. Dari hasil ini dapat disimpulkan bahwa model mampu memprediksi data baru.

Correct Classified dan Misclassified

Gunakan syntax berikut untuk melihat kasifikasi yang benar maupun klasifikasi yang salah.

# now storing some properly as well as misclassified indexes'.
i = 0
prop_class = []
mis_class = []

for i in range(len(Y_test)):
if(np.argmax(Y_test[i])==Y_pred_classes[i]):
prop_class.append(i)
if(len(prop_class)==8):
break

i=0
for i in range(len(Y_test)):
if(not np.argmax(Y_test[i])==Y_pred_classes[i]):
mis_class.append(i)
if(len(mis_class)==8):
break

Kasifikasi Benar

Berikut ini contoh klasifikasi yang benar.

count = 0
fig,ax = plt.subplots(4,2)
fig.set_size_inches(15,15)
for i in range (4):
for j in range (2):
ax[i,j].imshow(X_test[prop_class[count]])
ax[i,j].set_title("Predicted Flower : "+str(le.inverse_transform([Y_pred_classes[prop_class[count]]]))+"\n"+
"Actual Flower : "+str(le.inverse_transform(np.argmax([Y_test[prop_class[count]]]).reshape(1,-1))))
plt.tight_layout()
count+=1

Maka akan diperoleh hasil sebagai berikut.

Salah Kasifikasi

Berikut ini contoh klasifikasi yang salah.

count = 0
fig,ax = plt.subplots(4,2)
fig.set_size_inches(15,15)
for i in range (4):
for j in range (2):
ax[i,j].imshow(X_test[mis_class[count]])
ax[i,j].set_title("Predicted Flower : "+str(le.inverse_transform([Y_pred_classes[mis_class[count]]]))+"\n"+
"Actual Flower : "+str(le.inverse_transform(np.argmax([Y_test[mis_class[count]]]).reshape(1,-1))))
plt.tight_layout()
count+=1

Maka akan diperoleh hasil sebagai berikut.

Part selanjutnya akan membahas tentang pre-trained model CNN. Sekilas tentang pre-trained model, pre-trained model merupakan suatu metode yang memanfaatkan model yang telah dilatih sebelumnya untuk mengatasi permasalahan baru dengan cara menjadikannya sebagai titik awal kemudian dilakukan pembaruan parameter sehingga cocok digunakan untuk permasalahan baru tersebut. Biasanya pre-trained model ini telah diatih pada data yang besar sehingga seringkali pre-trained model ini dijadikan solusi untuk data dengan jumlah yang sedikit.

Sekian dan terima kasih.

Lanjut Part III: Mengenal Pre-trained Model CNN

--

--

Muchamad Nur Kholis
Muchamad Nur Kholis

Written by Muchamad Nur Kholis

Statistician and Data Scientist in Islamic University of Indonesia. LinkedIn Profile: linkedin.com/in/muchammad-nur-kholis-6844161ba

No responses yet