มาสร้าง Image Recognition ด้วย Convolutional Neural Networks (CNN) กันเถอะ

Patompat Kamtar
4 min readJan 3, 2019

--

สำหรับหลายๆ คนที่เคยใช้งาน Social Media มา ก็อาจจะเคยได้เห็นถึงความฉลาดของมันในการระบุตัวตนของใบหน้าที่อยู่ในรูปภาพ ชนิดที่ว่าแค่รูปที่มีขนาดเล็กๆ ก็สามารถระบุได้ว่าในรูปนั้นเป็นใคร

แต่หลายคนอาจจะยังไม่รู้ว่ากระบวนการทำงานของการวิเคราะห์ใบหน้านั้นเกิดขึ้นได้อย่างไร

วันนี้ผมเลยเขียนบทความขึ้นมาเพื่ออธิบายถึงวิธีการทำงานเบื้องต้นของกระบวนการจำแนกภาพ หรือ Image Recognition

โดยบทความนี้จะแบ่งออกเป็น 2 ส่วน

ในส่วนแรกจะเป็นการอธิบายถึงทฤษฎี Convolutional Neural Networks หรือ CNN ซึ่งเป็นทฤษฎีที่เรานำมาใช้เพื่อจำแนกรูปภาพ

และในส่วนที่สองจะเป็นวิธีการ และขั้นตอนในการสร้างโมเดลขึ้นมา

Convolutional Neural Networks หรือ CNN คืออะไร?

สำหรับเด็กเล็กๆ การจะเรียนรู้ได้ว่าวัตถุที่เห็นอยู่ตรงหน้าคืออะไร ก็จะต้องเกิดจากการจดจำผ่านก็เห็นซ้ำแล้วซ้ำอีก

ซึ่งสำหรับคอมพิวเตอร์แล้วการจดจำนั้นแตกต่างออกไป เพราะในโลกของคอมพิวเตอร์มีเพียงแค่ตัวเลขเท่านั้น และคอมพิวเตอร์จะแสดงผลของรูปภาพออกมาในรูปของตัวเลขแบบ 2 มิติ (2 dimensionals) เท่านั้น ซึ่งเราจะคุ้นเคยกับคำว่า pixels นั่นแหละครับ

ดังนั้นจะเห็นได้ว่าการที่จะสอนให้คอมพิวเตอร์จดจำ และจำแนกภาพได้นั้น ต้องมีอัลกอลิทึ่มเข้ามาช่วย ซึ่ง Convolutional Neural Networks หรือ CNN ก็คือตัวช่วยนั้นนั่นเอง

การแยกประเภทของรูปภาพแมว ระหว่างคน (เห็นเป็นรูปแมว) กับคอมพิวเตอร์ (เห็นเป็น matrix)

แล้ว CNN ทำงานยังไงกันหล่ะ???

CNNs จะมีองค์ประกอบอยู่ 2 ส่วนใหญ่ๆ ได้แก่

1. ส่วนของ Hidden layers หรือ Feature extraction โดยในส่วนนี้จะมีส่วนย่อยที่ทำงานร่วมกันอีก 3 ส่วน คือ

  • Convolution ซึ่งเป็นขั้นตอนของการสแกนรูปจาก input โดยจะมีการสร้าง filters (kernels) ขึ้นมาในรูปแบบของ matrix หลังจากนั้นก็จะทำการตรวจสอบ feature เพื่อหาลักษณะ หรือองค์ประกอบต่างๆ ของรูปภาพแต่ละรูป
  • ReLU จะเป็นขั้นตอนที่ทำให้ CNN เกิดการเรียนรู้ข้อมูลที่ได้รับมาจากขั้นตอนการตรวจสอบรูปภาพก่อนหน้า โดยข้อมูลจะถูกแปลงมาอยู่ในรูปของ non-linear โดยจะมีการใช้ activation function อย่าง Rectified Linear Unit (ReLU) เพื่อเข้ามาช่วยเพิ่มประสิทธิภาพของ CNN
  • Pooling จะทำการลดขนาดของรูปภาพให้เล็กลง เพื่อให้การทำงานของ CNN มีความรวดเร็วมากขึ้น และยังลดการใช้พื้นที่ความจำลงได้อีกด้วย

2. ส่วนของ Classification หลังจากผ่านขั้นตอนของ Hidden layers หรือ Feature extraction แล้ว ต่อมาในส่วนของ classification จะประกอบไปด้วย layer แบบ fully connected (จะเชื่อมกับทุก node ของ layer ก่อนหน้า) ซึ่งจะรับข้อมูลได้เพียง 1 มิติ (1 Dimensional) เท่านั้น ทำให้ต้องมีนำกระบวนการที่เรียกว่า Flatten เข้ามาช่วยในการแปลงข้อมูลจาก 3 มิติ ให้กลายเป็น 1 มิติเสียก่อน

รูปภาพแสดงการทำงานของ CNN

เอาล่ะครับ!!! หลังจากที่ได้รู้เกี่ยวกับทฤษฎีไปคร่าวๆ แล้ว ต่อมาก็ถึงเวลาที่จะต้องมาลองลงมือทำกันบ้างแล้ว…

โดยบทความนี้ผมจะทำการสร้างโมเดลบน Jupyter Notebook ซึ่งหากใครยังไม่เคยลง ก็สามารถค้นหาวิธีลง และทำตามขั้นตอนได้อย่างง่ายๆ เลยครับ

เอาหล่ะ…มาเริ่มกันเลยดีกว่า!!!

.

.

ผมเริ่มต้นจากการดาวน์โหลดชุดข้อมูล Flowers Recognition เข้ามาก่อน

โดยชุดข้อมูลนี้จะเป็นรูปภาพของดอกไม้จำนวน 4,242 ดอก ซึ่งถูกแบ่งตามประเภทของดอกไม้ออกเป็น 5 กลุ่ม (จะมี 5 โฟลเดอร์)

ชุดข้อมูลจะทำการเก็บรูปภาพของดอกไม้แต่ละประเภทเอาไว้ตามชื่อ

เมื่อดาวน์โหลดชุดข้อมูลมาเรียบร้อยแล้ว เราก็จะมาเปิด Jupyter Notebook ขึ้นมา

หลังจากนั้น ผมจะเอาไฟล์ที่ดาวน์โหลดมาอัพโหลดขึ้นไปบน Jupyter (สำหรับในตัวอย่างผมใช้ไฟล์ zip)

อัพโหลดชุดข้อมูลไปยัง Jupyter Notebook
หลังจากอัพโหลดเรียบร้อยแล้ว ก็จะเจอโฟลเดอร์หน้าตาแบบนี้

ต่อมาเราก็จะทำการเปิดหน้า Notebook ใหม่ขึ้นมา

หน้าตา Notebook ใหม่

เราจะทำการแตกไฟล์ zip ออกมาก่อน ในกล่องแรก

import zipfile
unzip = zipfile.ZipFile(“flowers.zip”, ‘r’)
unzip.extractall(“flowers”)

โดยในบรรทัดที่ 2 “flowers.zip” คือการระบุไฟล์ที่เราต้องการจะแตก

และในบรรทัดที่ 3 “flowers” คือชื่อที่เราจะตั้งให้กับไฟล์หรือโฟลเดอร์ที่เราได้ทำการแตกออกมา

เราจะพบว่า มีโฟลเดอร์ flowers เพิ่มขึ้นมาในหน้า Directory ของเรา

ต่อมาเราจะทำการ import สิ่งที่เราจำเป็นต้องใช้เข้ามาก่อน

from keras.models import Sequential
from keras.layers import Dense, Conv2D, MaxPooling2D, Dropout, Flatten
from keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
จะมีแถบชมพูแบบนี้ขึ้นมาหลังจากกด run

ถ้าสังเกตุชุดข้อมูลที่เรามีจะพบว่า ชุดข้อมูลจะถูกแยกออกมาตามประเภทของดอกไม้แต่ละชนิดเท่านั้น ไม่ได้มีการแบ่งชุดข้อมูลสำหรับ Train และ Validation ออกมาให้

เราจึงจะต้องทำการแบ่งส่วนของข้อมูลออกมาเพื่อใช้สำหรับการ Train และ Validation

โดยครั้งนี้จะทำการแบ่งข้อมูลสำหรับทำ validation ออกมา 30% (validation_split=0.3)

train = ImageDataGenerator(rescale=1.0/255.0,horizontal_flip=True, shear_range=0.2, zoom_range=0.2,width_shift_range=0.2,height_shift_range=0.2, fill_mode=’nearest’, validation_split=0.3)img_size = 128
batch_size = 25
train_steps = 3462/batch_size
validation_steps = 861/batch_size
traindata = train.flow_from_directory(“flowers/flowers”, target_size = (img_size, img_size), batch_size = batch_size, class_mode=’categorical’, subset=’training’)
validationdata = train.flow_from_directory(“flowers/flowers”, target_size = (img_size, img_size), batch_size = batch_size, class_mode = ‘categorical’, subset=’validation’)
แถบด้านล่างจะแสดงข้อมูลที่ถูกแบ่งสำหรับ Train และ Validation

เมื่อแบ่งข้อมูลสำหรับ Train และ Validation เรียบร้อยแล้ว เราก็จะมาสร้างโมเดลกัน!!!

โดยเราจะต้องกำหนดองค์ประกอบต่างๆ ที่เป็นวิธีการของ CNN ให้ครบถ้วน (ยังจำได้อยู่มั๊ยว่ามีอะไรบ้าง???)

#ส่วนนี้คือองค์ปรกอบของ CNN ที่ได้พูดไปแล้วในตอนต้น
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(img_size, img_size, 3), padding=’same’, activation=’relu’))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3), activation=’relu’, padding=’same’))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(128, (3, 3), activation=’relu’, padding=’same’))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dropout(0.2))
model.add(Dense(512, activation=’relu’))
model.add(Dense(5, activation=’softmax’))

model.compile(loss=’categorical_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])
print(model.summary())
ผลลัพธ์ที่ออกมาหลังจากทำการสร้างโมเดล

หลังจากนั้นเราจะทำการคำนวณออกมาว่าตัวโมเดลที่เราสร้างขึ้นมามีประสิทธิภาพดีมากน้อยแค่ไหน

showmodel = model.fit_generator(traindata, steps_per_epoch=train_steps, epochs=25, validation_data=validationdata, validation_steps=validation_steps)
เมื่อ run เสร็จก็จะได้ผลลัพธ์แบบนี้

เรายังสามารถสร้างกราฟที่แสดงถึงค่า accuracy และค่า loss ออกมาได้อีกด้วย

#กราฟแสดงค่าaccuracy
plt.plot(model_hist.history[‘acc’])
plt.plot(model_hist.history[‘val_acc’])
plt.title(‘model Accuracy’)
plt.ylabel(‘accuracy’)
plt.xlabel(‘epoch’)
plt.legend([‘train’, ‘test’], loc=’upper left’)
plt.show()
#กราฟแสดงค่าloss
plt.plot(model_hist.history[‘loss’])
plt.plot(model_hist.history[‘val_loss’])
plt.title(‘model Loss’)
plt.ylabel(‘loss’)
plt.xlabel(‘epoch’)
plt.legend([‘train’, ‘test’], loc=’upper left’)
plt.show()
จะได้กราฟออกมาในลักษณะนี้

เพียงเท่านี้เราก็จะสามารถสร้างโมเดล CNN เบื้องต้น สำหรับการทำ Image Recognition ได้แล้วครับ

Future work

การสร้างโมเดลสำหรับ Image Recognition ในครั้งนี้ เป็นเพียงการสร้างในเบื้องต้น และจำนวนรูปภาพก็อาจจะยังไม่มาก หรือหลากหลายเท่าที่ควร ซึ่งอาจจะทำให้ยังได้ค่าความแม่นยำที่ไม่มากนัก

ดังนั้นในอนาคตอาจจะลองนำเทคนิคของ Data Augmentation เข้ามาช่วย เพื่อทำให้โมเดลมีความแม่นยำมากยิ่งขึ้น

References
- https://www.learnopencv.com/image-classification-using-convolutional-neural-networks-in-keras/
- https://towardsdatascience.com/applied-deep-learning-part-4-convolutional-neural-networks-584bc134c1e2
- https://towardsdatascience.com/convolutional-neural-networks-from-the-ground-up-c67bb41454e1
- http://cs231n.github.io/classification/
- http://cs231n.github.io/convolutional-networks/

--

--

Patompat Kamtar
Patompat Kamtar

Written by Patompat Kamtar

Dataภาษาคน | Data Scientist | Investor | ENTJ man | Husband | Uncle

No responses yet