เรามาลองเล่นกับ Deep Learning กันบ้างดีกว่า เอาง่ายๆ ว่าเราจะสอนให้คอมพิวเตอร์มันดูภาพแล้วบอกได้ว่า "ภาพนี้คือหมา" หรือ "ภาพนี้คือแมว" แบบไม่ต้องให้มันจำเป๊ะๆ แต่ให้มันเข้าใจรูปแบบของภาพจากลักษณะต่างๆ ซึ่งการจำแนกแมวกับสุนัขในภาพมันไม่ยากเลยถ้าเรารู้จัก Convolutional Neural Network (CNN) ซึ่งเป็นโมเดลที่ใช้กันเยอะในการทำงานเกี่ยวกับภาพ
โดยหลักการของ CNN ที่ใช้ในบทความนี้จะประกอบไปด้วยดังนี้
Convolutional Layers (ดึงลักษณะสำคัญจากภาพ) ->> Pooling Layers(ย่อขนาดภาพให้เล็กลง ->> Fully Connected Layers (ทำนายว่าเป็น แมว หรือ สุนัข)

บทความนี้เราจะรันโค้ดใน Kaggle โค้ดที่เราจะใช้วันนี้เป็นโมเดล CNN ซึ่งเหมาะกับงานจำเเนกภาพเเบบ binary classification (เเมว vs สุนัข) ซึ่ง CNN จะช่วยดึงลักษณะต่างๆในภาพ เช่น ขอบ รูปร่าง เเละสี เเล้วใช้ sigmoid activation ที่ขั้นสุดท้ายในการให้คอมพิวเตอร์มันตัดสินใจว่า ภาพนี้เป็นหมาหรือเป็นเเมวกันนะ เรามาเริ่มทำตามทีละขั้นตอนกันเลย

ข้อมูล Dataset ที่ใช้ในบทความนี้
https://www.kaggle.com/code/kashit/cat-and-dog-classification-with-cnn/data

ขั้นตอนที่ 1 นำเข้าไลบรารี

import keras
from keras.models import Sequential
from keras.layers import Dense, Conv2D, MaxPooling2D, Flatten
from keras.preprocessing.image import ImageDataGenerator

ขั้นตอนที่ 2 เตรียมข้อมูลภาพด้วย ImageDataGenerator

train_data = ImageDataGenerator(rescale=1./255)
test_data = ImageDataGenerator(rescale=1./255)

ขั้นตอนที่ 3 อ่านข้อมูลจาก Dataset

train_path = '../input/cat-and-dogs/dataset/training_set'
train_set = train_data.flow_from_directory(directory=train_path, target_size=(128, 128), batch_size=32, color_mode="rgb", class_mode='binary')

test_path = '../input/cat-and-dogs/dataset/test_set'
validation_set = test_data.flow_from_directory(directory=test_path, target_size=(128, 128), batch_size=30, shuffle=True, class_mode='binary', color_mode="rgb")

เราใช้ flow_from_directory() ในการโหลดภาพจาก Dataset ที่เราโหลดมาเพื่อเก็บข้อมูลแมวและสุนัข โดยจะปรับขนาดภาพเป็น 128x128 และใช้ class_mode='binary' เพื่อจำแนกแค่ 2 คลาส คือ แมวเเละสุนัข เเละจะนำข้อมูลภาพมาทำการ train เเละ test

ผลการรันโค้ดจากขั้นตอนที่ 3

Image description

ขั้นตอนที่ 4 สร้างโมเดล CNN

cnn = Sequential()

cnn.add(Conv2D(32,(3,3),input_shape=(128,128,3),activation='relu'))
cnn.add(MaxPooling2D(pool_size=(2,2)))

cnn.add(Conv2D(64,(3,3),activation='relu'))
cnn.add(MaxPooling2D(pool_size=(2,2)))

cnn.add(Flatten())

cnn.add(Dense(256,activation='relu'))
cnn.add(Dense(1,activation='sigmoid'))

เราสร้าง CNN โดยเริ่มจาก Convolutional Layer จากที่อธิบายไปข้างต้นของบทความ เพื่อดึงคุณลักษณะจากภาพ จากนั้นใช้ MaxPooling เพื่อลดขนาดภาพให้เล็กลง แล้วนำข้อมูลมาผ่าน Flatten Layer และสุดท้ายจะใช้ Dense Layer ในการให้คอมพิวเตอร์มันทำนายว่าเป็น แมว หรือสุนัข

ขั้นตอนที่ 5 ดูโครงสร้างของโมเดลเรา

cnn.summary()

ผลการรันโค้ดจากขั้นตอนที่ 5

Image description

ขั้นตอนที่ 6 ทำการคอมไพล์โมเดล

cnn.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])

เราคอมไพล์โมเดลโดยจะใช้ Adam optimizer ทำให้การฝึกโมเดลเร็วและมีประสิทธิภาพ และใช้ binary_crossentropy สำหรับ binary classification

ขั้นตอนที่ 7 ฝึกโมเดล

model_history=cnn.fit(train_set,validation_data=validation_set,epochs=50)

ผลการรันโค้ดจากขั้นตอนที่ 7

Image description

Image description

โดยตัวอย่างผลการรันนี้เราจะใช้ epochs = 50 เเละผลการรันนี้จะมีการเปรียบเทียบกันการฝึกโมเดลระหว่าง epochs 10 เเละ epochs 50 ด้วย เพราะได้ลองฝึกเเละรันดูเเล้วเปรียบเทียบกันปรากฎว่าคอมพิวเตอร์อ่านได้ต่างกัน ในช่วง epochs 1-10 จะสังเกตุว่า โมเดลของเราค่อยๆเรียนรู้และปรับตัวดีขึ้น ค่า loss ลดลงจาก 0.7692 ไปที่ 0.0137 และ accuracy เพิ่มขึ้นจาก 0.5757 เป็น 0.9973 ซึ่งแสดงให้เห็นว่าโมเดลเริ่มทำงานได้ดีขึ้นเมื่อใช้เวลาฝึกได้เยอะขึ้น

เเต่เมื่อเราเพิ่มจำนวน epochs เป็น 50 ค่า loss มันจะต่ำมากและ accuracy ขึ้นไปถึง 100% ซึ่งหมายความว่าโมเดลทำการจำแนกได้แม่นยำขึ้นอย่างมาก ทีนี้มันจะเป็นเหตุผลที่ epochs 10 เเละ epochs 50 ต่างกัน ยิ่งฝึกนานเท่าไหร่จะยิ่งเเม่นยำมากขึ้นเท่านั้น ถ้าอยากลองสามารถลองได้

(train_set,validation_data=validation_set,epochs=50) ปรับจำนวนครั้งในการฝึก ที่ epochs ตามที่เราต้องการได้
(ใช้เวลาการฝึกนานตาม epochs ยิ่งมากก็ยิ่งนานเเต่ความเเม่นยำเพิ่มขึ้น)

ขั้นตอนที่ 8 ทำการ plot กราฟออกมาดู

import matplotlib.pyplot as plt
import numpy as np
N = 50
plt.style.use("ggplot")
plt.figure()
H=model_history

plt.plot(np.arange(0, N), H.history["accuracy"], label="train_acc")
plt.plot(np.arange(0, N), H.history["val_accuracy"], label="val_accuracy")

plt.title("Training and validation Accuracy on Dataset")
plt.xlabel("Epoch #")
plt.ylabel("Loss/Accuracy")
plt.legend(loc="lower left")

รูปกราฟ

Image description

ขั้นตอนที่ 9 ทดสอบผลที่ฝึกมา

import numpy as np
from keras.preprocessing import image
test_image = image.load_img('../input/cat-and-dogs/dataset/single_prediction/cat_or_dog_2.jpg', target_size = (128,128))
test_image = image.img_to_array(test_image)
test_image = np.expand_dims(test_image, axis = 0)
result = cnn.predict(test_image)
train_set.class_indices
if result[0][0] == 1:
    prediction = 'dog'
else:
    prediction = 'cat'
print(prediction)

plt.imshow(test_image[0].astype('uint8'))  
plt.title(f"Prediction: {prediction}")
plt.show()

ผลการรันโค้ดทดสอบผล

นำภาพ dataset เป็นภาพ สุนัขเเละเเมว เเบบ single_prediction ที่ให้คอมพิวเตอร์ที่เราทำการฝึกโมเดลมาเเล้ว ทำการทำนายภาพที่ให้ไป ว่า คือ เเมวหรือสุนัข ดังภาพตัวอย่างการรัน

Image description

Image description

ตัวอย่างเพิ่มเติม
เราจะใช้ตัวอย่างภาพที่เป็น pizza เเละ notpizza กันบ้าง ให้คอมพิวเตอร์ได้บอกมาว่า ภาพนี้ใช่พิซซ่าหรือไม่ ซึ่งตัวอย่างนี้จะเป็นชุดข้อมูลที่ได้สร้างขึ้นมาเองเเละมีความน่าสนใจเเละคล้ายคลึงกันกับสิ่งที่ทำไปข้างต้น เรามาลองดูกัน

dataset ที่ใช้ https://www.kaggle.com/datasets/code78csr/pizza-or-notpizza

ขั้นตอนที่ 1 นำเข้าไลบรารี

import keras
from keras.models import Sequential
from keras.layers import Dense,Conv2D,MaxPooling2D,Flatten
from tensorflow.keras.preprocessing.image import ImageDataGenerator

ขั้นตอนที่ 2 อ่านข้อมูลจาก Dataset

train_path='/kaggle/input/pizza-or-notpizza/pizza vs notpizza/training_set'
train_set=train_data.flow_from_directory(directory=train_path,target_size=(128,128),batch_size=32,color_mode="rgb",class_mode = 'binary')
test_path='/kaggle/input/pizza-or-notpizza/pizza vs notpizza/test_set'
validation_set=test_data.flow_from_directory(directory=test_path,target_size=(128,128),batch_size=30,shuffle=True,class_mode = 'binary',color_mode="rgb")

ใช้ Dataset ที่เราโหลดมาเปลี่ยนจากสุนัขและเเมว ที่ใช้ในการ train เเละ test เป็น Dataset pizza or notpizza

ขั้นตอนที่ 3 ดูโครงสร้างโมเดลเรา

cnn.summary()

ผลการรันโค้ดขั้นตอนที่ 3

Image description

ขั้นตอนที่ 4 ฝึกโมเดล

model_history=cnn.fit(train_set,validation_data=validation_set,epochs=50)

ผลการรันนี้เราจะใช้ epochs = 50 เหมือนเดิมกับตัวอย่างของสุนัขเเละเเมว

ผลการรันโค้ดขั้นตอนที่ 4

Image description

ขั้นตอนที่ 5 plot กราฟมาดูกัน

import matplotlib.pyplot as plt
import numpy as np
N = 50
plt.style.use("ggplot")
plt.figure()
H=model_history

plt.plot(np.arange(0, N), H.history["accuracy"], label="train_acc")
plt.plot(np.arange(0, N), H.history["val_accuracy"], label="val_accuracy")

plt.title("Training and validation Accuracy on Dataset")
plt.xlabel("Epoch #")
plt.ylabel("Loss/Accuracy")
plt.legend(loc="lower left")

ผลการรันโค้ดขั้นตอนที่ 5

Image description

ขั้นตอนที่ 6 ทดสอบผลที่ฝึกมา

import numpy as np
from keras.preprocessing import image
test_image = image.load_img('/kaggle/input/pizza-or-notpizza/pizza vs notpizza/single_prediction/pizza_or_notpizza_1.jpg', target_size = (128,128))
test_image = image.img_to_array(test_image)
test_image = np.expand_dims(test_image, axis = 0)
result = cnn.predict(test_image)
train_set.class_indices
if result[0][0] == 1:
    prediction = 'pizza'
else:
    prediction = 'notpizza'
print(prediction)

# Show the image with the prediction
plt.imshow(test_image[0].astype('uint8'))  # Convert array to uint8 for proper image display
plt.title(f"Prediction: {prediction}")
plt.show()

test_image = image.load_img('/kaggle/input/pizza-or-notpizza/pizza vs notpizza/single_prediction/pizza_or_notpizza_1.jpg', target_size = (128,128))
เปลี่ยน Path ของ Dataset ให้เป็นภาพ Pizza or NotPizza เป็นภาพเเบบ single_prediction ที่เป็นภาพ Pizza เเละภาพที่เป็นอาหารประเภทอื่น เพื่อทดสอบภาพเดี่ยวให้คอมพิวเตอร์ได้บอกมาว่า ใช่หรือไม่ใช่

prediction = 'pizza'
prediction = 'notpizza'

เปลี่ยน Pizza and NotPizza จากเดิมเป็น Cat and Dog เพื่อทดสอบให้ตรงกับภาพ Dataset ที่เราได้นำมาใช้ในการทดสอบ

ผลการรันโค้ดขั้นตอนที่ 6

Image description

Image description

สรุปผล
ในบทความนี้เราสร้างโมเดล Convolutional Neural Network (CNN) สำหรับจำแนกภาพ แมว กับ สุนัข และ พิซซ่า กับ ไม่พิซซ่า โดยใช้ Keras และ TensorFlow เพื่อช่วยให้คอมพิวเตอร์สามารถเข้าใจและจำแนกรูปภาพได้ดีขึ้น โดยการใช้ Convolutional Layers เพื่อดึงลักษณะสำคัญจากภาพ, Pooling Layers เพื่อลดขนาดภาพ และ Fully Connected Layers เพื่อทำนายว่าเป็นแมวหรือสุนัข รวมถึงภาพนี้เป็นพิซซ่าและไม่เป็นพิซซ่า เเละโมเดลนี้ฝึกด้วย ImageDataGenerator ที่ช่วยให้การโหลดและการเตรียมข้อมูลภาพทำได้ง่ายขึ้น พร้อมกับใช้ Adam Optimizer และ Binary Crossentropy ในการคอมไพล์โมเด เมื่อฝึกโมเดลเสร็จ เราใช้ epochs = 50 เพื่อให้โมเดลเรียนรู้ได้ดีที่สุด การทดสอบนี้สามารถนำไปประยุกต์ใช้กับชุดข้อมูลอื่น ๆ ได้โดยการเปลี่ยนแปลง dataset หรือ labels ตามที่ต้องการได้เลย ลองเล่นกันดู

Reference

  1. https://www.kaggle.com/code/kashit/cat-and-dog-classification-with-cnn/notebook

  2. https://medium.com/@korlakuntasaikamal10/deep-learning-cat-and-dog-classification-using-tensorflow-8011596d8f96