สร้างโมเดล Object Detection ตรวจจับหน้าแมว 😸
เนื้อหาในนี้สามารถอ่านแล้วทำตามไปด้วยได้เลย😎 แต่ก็ข้ามพื้นฐานหลายอย่าง ถ้าต้องการศึกษาพื้นฐานก่อน สามาถอ่านลิงค์นี้ได้ครับ
ผมเชื่อว่าหลายท่านน่าจะมีน้องแมวขี้อ้อนแสนน่ารักอยู่ที่บ้าน และหลายท่านก็อยากถ่ายทอดความน่ารักของน้องให้คนอื่นได้เห็น 🥰 เรามาลองถ่ายทอยความน่ารักของน้องให้ AI ได้เห็นกันดีมั้ยครับ!
สร้างโมเดล Object Detection ให้ AI ได้สบตากับน้องมากขึ้น ได้เห็นน้องบ่อยๆ และตกหลุมรักเช่นเดียวกับพวกเรา~

ผมเอา dataset มาจาก Kaggle ในนี้มีรูปน้องมากกว่า 5 หมื่นภาพ! 🙀 โดยใช้ MMDetection เป็นเครื่องมือในการสร้าง และทำบนระบบปฏิบัติการ Linux การติดตั้ง libray ที่ต้องใช้ สามารถดูได้ใน ลิงค์นี้ครับ
ขั้นตอนการทำแบ่งออกเป็น 3 ขั้นตอนหลักๆดังนี้
- เตรียม Dataset
- Train Model
- ใช้งาน Model
ก่อนอื่นเครื่องเราต้องมี library ที่จำเป็นต้องใช้ก่อน คือ PyTorch, MMDetection สามารถดูวิธีติดตั้งได้ ที่นี่ และ scikit-learn กรณีใช้ cona ติดตั้งโดยใช้คำสั่ง
conda install scikit-learn
1. เตรียม Dataset
หลังจากโหลด dataset มา ข้อมูลจะอยู่ใน result-dataset/result-dataset/
คือ coco.json
และโฟลเดอร์ data
ที่มีรูปน้องอยู่ 5,1453 ภาพ
เนื่องจากไฟล์ json มีอยู่ไฟล์เดียว ดังนั้นเราต้องแบ่งข้อมูลออกเป็น train, valid, test เอง
import json
from sklearn.model_selection import train_test_split
# เปิดไฟล์ และอ่านค่าจาก coco.json
with open("result-dataset/result-dataset/coco.json", 'r') as file:
data = json.load(file)
# เก็บรายชื่อไฟล์รูปภาพไว้ใน img_list
img_list = data["images"]
# แบ่งข้อมูลออกเป็น train:70%, valid:15%, test:15%
train_data, temp_data = train_test_split(img_list, test_size=0.3, random_state=42)
valid_data, test_data = train_test_split(temp_data , test_size=0.5, random_state=42)
# นำข้อมูลเก็บในตัวแปรใหม่ เพื่อเตรียมบันทึกในไฟล์ json
train_dict = {
"annotations": data["annotations"].copy(),
"categories": data["categories"].copy(),
"images": train_data
}
valid_dict = {
"annotations": data["annotations"].copy(),
"categories": data["categories"].copy(),
"images": valid_data
}
test_dict = {
"annotations": data["annotations"].copy(),
"categories": data["categories"].copy(),
"images": test_data
}
# บันทึกไฟล์ json ใหม่
with open("result-dataset/result-dataset/train.json", 'w') as file:
json.dump(train_dict, file)
with open("result-dataset/result-dataset/valid.json", 'w') as file:
json.dump(valid_dict, file)
with open("result-dataset/result-dataset/test.json", 'w') as file:
json.dump(test_dict, file)
เมื่อเสร็จจะได้ไฟล์ใหม่ออกมาคือ train.json
, valid.json
และ test.json
ข้อมูลของเราก็พร้อมสำหรับการ train model เป็นที่เรียบร้อย
2. Train Model
ก่อนอื่นเราต้องเข้าไปแก้ไขชื่อ class ในไฟล์ mmdetection/mmdet/datasets/coco.py
ให้ตรงกับที่ระบุในไฟล์ json โดยในไฟล์ json ระบุชื่อ class นี้ว่า “face” ดังนั้นใน coco.py
ที่ METAINFO['classes']
ระบุว่า 'face',
ดังภาพด้านล่าง

ต่อมาโหลด pretrained model เพื่อทำการ transfer learning โดยโมเดลที่ผมเลือกใช้คือ Cascade R-CNN, สามารถโหลดได้จาก ลิงค์นี้
หรือเพื่อความรวดเร็วสามารถสั่งผ่าน command line ว่า
wget https://download.openmmlab.com/mmdetection/v2.0/cascade_rcnn/cascade_rcnn_x101_64x4d_fpn_20e_coco/cascade_rcnn_x101_64x4d_fpn_20e_coco_20200509_224357-051557b1.pth

เมื่อโหลดเสร็จจะได้ไฟล์ชื่อว่า
cascade_rcnn_x101_64x4d_fpn_1x_coco_20200515_075702-43ce6a30.pth
หลังจากนั้นแก้ไขค่าใน config file โดยใช้ config file ที่ตรงกับโมเดลที่โหลด
from mmengine.config import Config
# อ่าน config file ของโมเดลที่จะใช้
cfg = Config.fromfile("mmdetection/configs/cascade_rcnn/cascade-rcnn_x101-64x4d_fpn_1x_coco.py")
# กำหนดจำนวน class
for bbox_head in cfg.model.roi_head.bbox_head:
bbox_head.num_classes = 1
# กำหนดเป็น auto scale learning rate และ batch size
cfg.auto_scale_lr.base_batch_size = 4
cfg.auto_scale_lr.enable = True
cfg.auto_scale_lr.base_batch_size, cfg.auto_scale_lr.enable
# กำหนด path ของข้อมูล ทั้ง train, valid และ test
cfg.data_root = "result-dataset/result-dataset/"
cfg.train_dataloader.dataset.data_root = "result-dataset/result-dataset/"
cfg.train_dataloader.dataset.data_prefix.img = "data"
cfg.train_dataloader.dataset.ann_file = "train.json"
cfg.val_dataloader.dataset.data_root = "result-dataset/result-dataset/"
cfg.val_dataloader.dataset.data_prefix.img = "data"
cfg.val_dataloader.dataset.ann_file = "valid.json"
cfg.test_dataloader.dataset.data_root = "result-dataset/result-dataset/"
cfg.test_dataloader.dataset.ann_file = "test.json"
cfg.test_dataloader.dataset.data_prefix.img = "data/"
cfg.val_evaluator.ann_file = "result-dataset/result-dataset/valid.json"
cfg.test_evaluator.ann_file = "result-dataset/result-dataset/test.json"
# กำหนดจำนวน epoch
cfg.train_cfg.max_epochs = 5
# กำหนด pretrained model ที่จะใช้
checkpoint_file = "cascade_rcnn_x101_64x4d_fpn_20e_coco_20200509_224357-051557b1.pth"
cfg.load_from = checkpoint_file
# บันทึก config file หลังแก้ไข
cfg.dump('my_config.py')
สั่ง train โมเดล โดยระบุว่าใช้ GPU หมายเลข 2 (ไม่ใส่ CUDA_VISIBLE_DEVICES
ก็ได้)
CUDA_VISIBLE_DEVICES=2 python mmdetection/tools/train.py my_config.py --auto-scale-lr --work-dir=train_result/ > train_log.txt 2>&1
เมื่อ train โมเดลเสร็จจะได้ผลลัพธ์เก็บไว้ที่ train_result/
ตามที่ระบุเอาวันในคำสั่ง train
เรามาเช็คการเรียนรู้ของโมเดลระหว่างการ train โดยสร้างกราฟ loss function ด้วยคำสั่ง
python mmdetection/tools/analysis_tools/analyze_logs.py plot_curve train_result/20240318_210052/vis_data/scalars.json --keys bbox_mAP --legend bbox_mAP --title "Bounding Box Mean Average Precision" --out bbox_mAP.png
จะได้ภาพผลลัพธ์ออกมาชื่อว่า bbox_mAP.png

เพราะว่าเป็นสาธิตการทำ ก็เลยสั่ง train แค่ 5 epoch, กราฟอาจจะออกมาแปลกๆ 😅 แต่ก็ถือว่าโมเดลเรียนรู้ได้ดีตั้งแต่ epoch แรกแล้ว
3. ใช้งาน Model
เนื่องจากโมเดลมีค่า bbox mAP สูงสุดตอน epoch ที่ 3 ดังนั้นเราจะนำโมเดลนี้มาใช้
โมเดลหลังจากการ train ทุก epoch จะถูกบันทึกไว้ในโฟลเดอร์ train_result
เช่นกัน

ภาพน้องที่ใช้คือตัวอย่างแมวไทย 3 สายพันธุ์ได้แก่



โดยตั้งชื่อไฟล์ว่า wichianmat.jpg
, korat.jpg
และ bombay.jpg
เก็บไว้ในโฟลเดอร์ img_in/
คำสั่งสำหรับเรียกใช้งานโมเดลคือ
from mmdet.apis import DetInferencer
# โหลดโมเดลที่ train เอาไว้
my_model = DetInferencer(model="my_config.py", weights="train_result/epoch_3.pth", device="cuda")
# นำรูปภาพเข้าไปในโมเดล โดยให้ผลลัพธ์เก็บไว้ที่โฟลเดอร์ img_out
my_model("img_in/wichianmat.jpg", out_dir="img_out/")
my_model("img_in/korat.jpg", out_dir="img_out/")
my_model("img_in/bombay.jpg", out_dir="img_out/")
ภาพที่ออกมาคือ



เท่านี้ก็เสร็จเรียบร้อยแล้วครับสำหรับการฝึกให้ AI ได้สบตาน้องบ่อยๆ 😍
ลองเอาวิธีนี้ไปใช้กับแมวที่บ้านดูครับ~
อ้างอิง