ใช้ CNN อ่านตัวเลข MNIST ด้วย Keras และ PlaidML

บล็อกนี้ผมจะมาอธิบายถึงวิธีการสร้าง Model CNN เพื่อการทำ Digit Prediction โดยใช้ Keras กับ PlaidML แต่ผมจะยังไม่ทำการอธิบายการทำงานของ CNN แบบละเอียดในบทความนี้ แต่จะเน้นไปที่การเขียนโค้ดเพื่อใช้งานเลย

สำหรับคนที่ชอบอ่านโค้ดมากกว่าอ่านบทความ สามารถตรงไปอ่านโค้ดได้ข้างล่างนี้เลย

CNN หรือชื่อเต็มๆว่า Convolution Neural Network นั้น ถ้าให้อธิบายสั้นๆ ก็คือ Neural Network ที่มี layer อย่างน้องหนึ่งอันที่มีการทำ Convolution Convolution Operations รูปภาพจาก SuperDataScience

ประโยชน์หลักๆของมันเลยก็คือ ทำให้ Neural Network สามารถเลือก Features ที่ต้องการเพื่อมา Classify ได้ถูกต้องมากยิ่งขึ้น

Training Data

เราจะใช้ MNIST Database เป็นตัว Train และ Test model ของเรา หากใครเคยเรียนคอรส์ Machine Learning หรือ Data Science มาบ้างแล้วคงรู้จักเป็นอย่างดี

PlaidML คืออะไร

PlaidML เป็น tensor compiler คล้ายๆกับ Tensorflow แต่เหตุผลที่ผมเลือกใช้ตัวนี้เพราะว่าผมใช้ Macbook Pro และ Tensorflow ไม่ support การด์จอ AMD Radeon Pro 5500M ที่อยู่ในเครื่อง Macbook

เนื่องจาก PlaidML Support Keras โดยตรง การใช้งานก็งานนิดเดียวครับ เพียงลง PlaidML ก่อนดังนี้

pip install plaidml-keras plaidbench

ตั้งค่า plaidml

plaidml-setup

ก่อนเรียกใช้ keras ให้ตั้งแค่ Environment Variable ดังนี้

os.environ["KERAS_BACKEND"] = "plaidml.keras.backend"

แค่นี้โค้ด Keras ของคุณก็จะรันบนการด์จอที่ ใช้ OpenCL หรือ Apple Metal แล้วครับ

CNN Model

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 26, 26, 32)        320       
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 24, 24, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 12, 12, 64)        0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 12, 12, 64)        0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 9216)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 128)               1179776   
_________________________________________________________________
dropout_2 (Dropout)          (None, 128)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 10)                1290      
=================================================================
Total params: 1,199,882
Trainable params: 1,199,882
Non-trainable params: 0
_________________________________________________________________

คำอธิบาย Layer สั้นๆดังนี้

  1. เอารูปภาพขนาด 28x28 เข้า Convolution Layer ที่มี Filter 32 อัน และ Kernel ขนาด 3x3 สุดท้ายเอา Output ไปผ่าน ReLU
  2. เอา output จากขั้นตอนที่หนึ่ง เข้าไป Convolution อีกหนึ่งอันที่มี Filter 64 อัน และ Kernel ขนาด 3x3 และเอา Output ไปผ่าน ReLU
  3. เอา output จากขั้นตอนก่อนหน้าไปทำ MaxPooling โดยมี pool size ที่ 2x2 รูปภาพจะเหลือแค่ 12x12x64
  4. ทำการ Dropout ที่ 0.25
  5. ทำการ Flatten รูปเพื่อโยนเข้า Fully Connected Layer
  6. โยนเข้า Network ที่มี output 128 units
  7. ทำการ Dropout ที่ 0.5
  8. โยนเข้าอีก Fully connected layer โดย output มี 10 units ที่บอกถึงหมายเลข 0 - 9

Code 🎉

สามารถเข้าไปอ่านโค้ดขั้นตอนการ Train model ใน Keras ได้ที่ notebook ได้ล้าง

Jupyter Notebook

หรือจะเข้าไปดูวิธีการใช้งานในแอพพลิเคชั่นได้ที่ลิงค์ด้านล่างเลยครับ

Drawable digit prediction app using TensorflowJS

เว็บแอพด้านบนแปลง Model ที่ได้จากการ Train Keras ไปใช้ใน Tensorflow โดยการลง

pip install tensorflowjs

และทำการ convert model (.h5)

tensorflowjs_converter --input_format keras \
                       path/to/my_model.h5 \
                       path/to/tfjs_target_dir

วิธีการใช้งาน สามารถกดคลิกขวาดู Source code ของเว็บด้านบนได้เลยครับ ผมเขียนไว้ใน Plain Javascript