Object detection in white blood cell

Praewa Choobanna
6 min readJun 19, 2022

โดย นางสาวเเพรวา ชูบ้านนา สังกัด Mysterious-hedgehogs

ที่ปรึกษาโปรเจกต์ :

  • นพ.ปิยะฤทธิ์ อิทธิชัยวงศ์ (นักวิจัยด้านปัญญาประดิษฐ์ในภาพถ่ายทางการเเพทย์ รพ.ศิริราช ปัจจุบันศึกษาต่อระดับปริญญาเอก ที่ รพ.St.Thomas,King’s College London)
  • นายณัฐพล ไตรจักร์วนิช(นักวิจัยด้าน Transformer เเละ NLP ปัจจุบันศึกษาต่อระดับปริญญาเอกที่ VISTEC)

Github:https://github.com/praewery

ปัจจุบันเทคโนโลยีคอมพิวเตอร์ได้กลายเป็นสิ่งสำคัญที่เข้ามามีบทบาทกับชีวิตมนุษย์ในหลายๆด้าน รวมถึงด้านวิทยาศาสตร์เเละการเเพทย์ ได้มีการนำ Machine learning & AI เข้ามาเป็นส่วนนึงของการรักษา เพื่อพัฒนาให้การรักษามีประสิทธิภาพเเละ เเม่นยำมากยิ่งขึ้น !

Leukemia หรือ มะเร็งเม็ดเลือดขาว

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

มะเร็งเม็ดเลือดขาวชนิดเฉียบพลันจัดเป็นโรคมะเร็งที่มีความรุนแรงสูง พบได้ทุกเพศทุกวัย พบมากขึ้นในผู้สูงอายุ และเป็น 1 ใน 10 โรคมะเร็งที่พบบ่อยในประเทศไทย

มะเร็งเม็ดเลือดขาวสามารถแบ่งได้หลายแบบ ได้แก่ แบ่งตามระยะการเกิดโรค และแบ่งตามชนิดของเซลล์มะเร็ง

แบ่งตามระยะเวลาเกิด

  1. มะเร็งเม็ดเลือดขาวชนิดเฉียบพลัน (acute leukemia) คือการที่เซลล์ตัวอ่อนของเม็ดเลือดขาวแบ่งตัวอย่างรวดเร็ว อาการของโรคจะเกิดขึ้นอย่างฉับพลันและรุนแรง ผู้ป่วยจึงจำเป็นต้องได้รับการรักษาอย่างทันท่วงที
  2. มะเร็งเม็ดเลือดขาวชนิดเรื้อรัง (chronic leukemia) คือการที่เซลล์เม็ดเลือดขาวถูกผลิตออกมามากเกินไป ทำให้ผู้ป่วยมีเม็ดเลือดขาวมากกว่าปกติ เนื่องจากความผิดปกติเกิดขึ้นอย่างช้าๆ ผู้ป่วยอาจไม่มีอาการผิดปกติใดๆ เลยเป็นเวลานับปี แต่สามารถตรวจพบได้จากการตรวจเลือด

แบ่งตามชนิดของเซลล์มะเร็ง

  1. มะเร็งเม็ดเลือดขาวชนิดมัยอีโลจีนัส (myelogenous leukemia) เป็นชนิดของมะเร็งที่เกิดจากเซลล์ในสาย myeloid เติบโตผิดปกติ
  2. มะเร็งเม็ดเลือดขาวชนิดลิมโฟซิติก (lymphocytic leukemia) เป็นชนิดของมะเร็งที่เกิดจากเซลล์ในสาย lymphoid

ทั้งนี้ การแบ่งชนิดของมะเร็งเม็ดเลือดขาวจะมีผลต่อการเลือกวิธีการรักษา เนื่องจากมะเร็งเม็ดเลือดขาวแต่ละชนิดมีการดำเนินโรคและการพยากรณ์โรคที่แตกต่างกัน

ในปัจจุบันการวินิจฉัยมะเร็งเม็ดเลือดขาว จะทำการตรวจไขกระดูก(Bone marrow smear or biopsy)หรือการดูจากเลือดที่เจาะจากหลอดเลือดดำ(vein)เช่น ที่เเขน โดยทั้งสองวิธีนั้นจะนำเลือดมาไถดูบนสไลด์ เพื่อดูผ่านกล้องจุลทรรศน์ เรียกว่า (peripheral blood smear) เพื่อนับจำนวนเซลล์ตัวอ่อน เเละเเยกชนิดของเซลล์ เพื่อพยากรณ์โรค ทั้งนี้ การเเบ่งชนิดของมะเร็งเม็ดเลือดขาวจะมีผลต่อการเลือกวิธีการรักษาทำให้สำคัญมากๆ จำเป็นต้องอาศัยบุคลากรทางการเเพทย์เเละผู้เชี่ยวชาญในการจำเเนก จึงเป็นเหตุผลที่ดีถ้าเราจะนำ AI เข้าไป screening tools ช่วยบุคลากรทางการเเพทย์ เพื่อเพิ่มประสิทธิภาพทางการรักษาได้มากยิ่งขึ้น!

เรามาเริ่มกันเลยย Let’s go!!

Dataset image

การพัฒนา model ครั้งนี้ ผู้จัดทำได้ใช้ dataset microscopic image of white blood cells จาก โรงพยาบาลศิริราช โดยภายใน Dataset ประกอบด้วยรูปภาพ ตัวอ่อนของเม็ดเลือดขาวของกลุ่มคนประเภทหนึ่ง ซึ่งสามารถเเบ่งเป็น 12 ชนิดด้วยกันได้เเก่ Atypical lymphocyte, Band Neutrophil, Basophil, Blast, Eosinophil, Lymphocyte, Metamyelocyte, Monocyte, Myelocyte, NRC, Promyelocyte, Segmented neutrophil

Model

สำหรับ Model ผู้ศึกษาได้เลือกใช้ 3 Model ด้วยกัน นั้นก็คือ Faster_rcnn, yolov5 ที่สามารถใช้งานง่าย สะดวกรวดเร็ว เเละ Swin Transformer ซึ่งเป็นการนำ Transformer มาทำ Object detection โดยตัวTransformerเป็นโครงสร้างที่นิยมมากใน NLP มีจุดเด่นคือการทำ Self-attention ซึ่งจะต้องแบ่งข้อมูลออกเป็นส่วนย่อยๆก่อน สำหรับการทำ Object detection ข้อมูลจะถูกแบ่งออกเป็นพื้นที่เล็กๆที่เราเรียกว่า patch และนำเอาข้อมูลชิ้นเล็กเหล่านั้นมาเปรียบเทียบกันเองผ่าน dot product เพื่อโมเดลจะรู้ว่าควรจะโฟกัสที่ตรงไหน วิธีนี้มีข้อดี โดย แต่ละ patch ใน feature map ของแต่ละ layer จะมีการเปรียบเทียบหาความสัมพันธ์กับ patch อื่นๆทั้งภาพ

ในครั้งที่ เราได้สร้างโมเดล Swin Transformerผ่าน icevision ที่เป็นlibary ขนาดใหญ่ภายในมีโมเดลคุณภาพสูง จาก MMLabs ,Torchvision เเละ Pytorcch image Models เเละยังสามารถ train ด้วย Pytorch-Lightingเเละ Fastaiได้อีกด้วย

Model:YoloV5

**ตอนนี้ใน icevision มี yolov5 เเล้วนะ! เพื่อนๆสามารถเข้าไปtrain model ในนั้นได้เหมือนกันน

ผู้จัดทำได้ทำการเเบ่งชุดข้อมูลเป็น train , validation เเละ Testset ถูกเก็บใน floder ดังนี้

Dataset
-train
-image
-label
-valid
-image
-label
-test
-image

จากDatasetทั้งหมดจำนวน 3,376 ภาพ เป็น trainset จำนวน 2700 ภาพใน folder train , validation set จำนวน 338 ภาพใน folder valid เเละ test set จำนวน 338ภาพใน folder test โดยที่ชื่อไฟล์ระหว่าง image กับ label ต้องเหมือนกันด้วยนะ!

ต่อมาเราจะมาบอก Modelให้ทราบได้ว่า path เก็บข้อมูลอยู่ที่ไหน , จำนวน class , เเต่ละ class มีชื่ออะไรบ้าง ใน file coco128.yaml (เข้าไปที่folder yolov5 > data>coco128.yaml) ใส่ Path ข้อมูลของเราลงไป พร้อมเเก้ไขclass ให้เป็น class ของเราได้เลย

train: ../train/images #path train image
val: ../valid/images #path valid image
nc: 12 #จำนวนclass
names:['Atypical lymphocyte', 'Band Neutrophil', 'Basophil', 'Blast', 'Eosinophil', 'Lymphocyte', 'Metamyelocyte', 'Monocyte', 'Myelocyte', 'NRC', 'Promyelocyte', 'Segmented neutrophil']#ชนิดของclassทั้งหมด

เมื่อเราทำการ save ไฟล์ coco128.yaml ที่เเก้ไขไปข้างต้นเรียบร้อยเเล้ว ขั้นตอนถัดมาจะเป็นการ train model เราสามารถเลือกโมเดลที่ใช้ trainได้อย่างหลากหลายโดยวิเคราะห์จากเป้าหมายระยะเวลาเเละประสิทธิภาพ นี่คือตัวอย่างโมเดลที่คุณสามารถเลือกใช้ได้

ผู้จัดทำได้ทำการเลือกใช้ โมเดล YOLOv5s เนื่องจากมีความซับซ้อนที่ค่อนข้างน้อย

ต่อมาเมื่อเราเลือกโมเดลเป็นที่เรียบร้อยเเล้วในขั้นตอนนี้เราจะใช้คำสั่งดังนี้เพื่อเริ่มทำการ train โมเดล โดยกำหนดให้

  • img(ขนาดรูป)=640
  • batch (ขนาด batch size) = 16
  • epochs(จำนวนที่ใช้รัน) = 100
  • data(ตำเเหน่งconfiguration file) = coco128.yaml
  • weights(โมเดลที่เราเลือก) = yolov5s
#Train YOLOv5s on COCO128 for 100 epochs
!python train.py --img 640 --batch 16 epochs 100 --data coco128.yaml --weights yolov5s.pt --cache

สามารถดูผลลัพธ์ได้ที่ yolov5/runs/detect เเละนี่คือตัวอย่างผลลัพธ์ที่ได้หลังจาก train เสร็จเรียบร้อยเเล้ว

ไฟล์ val_batch1_label.jpg (บอกว่า label ที่เรากำหนดอยู่ตรงไหนบ้าง
ไฟล์val_batch1_pred.jpg(predict class อะไร,ความมั่นใจกี่เปอร์เซ็น)
confusion_matrix.png

ผลลัพธ์ที่ออกมาถือว่าไม่เลวเลยทีเดียว เเต่เมื่อวิเคราะห์ออกมาดีๆจะเห็นได้ว่าโมเดลของเรายัง detect เม็ดเลือดขาวชนิด Myelocyte ได้ไม่ดีเท่า 11 ชนิดที่เหลือ เนื่องจากโมเดลของเรายังสับสนละหว่าง Promyelocyte เเละ Myelocyte อยู่

***วิธีเเก้ไขที่ทำให้โมเดลของเรามีประสิทธิภาพมากยิ่งขึ้น ก็คือการทำ balance dataset ให้มากยิ่งขึ้นเเละ อาจจะเพิ่มจำนวน epoch ในการtrain ให้มากขึ้นไปอีก

Model: icevision (Swin Transformer)

มาเริ่มจากการใส่ path ของ dataset ที่เตรียมไว้สำหรับ train กัน! โดยครั้งนี้ผู้จัดทำได้ทำการเปลี่ยนเเปลงไฟล์ label เป็น Voc annotation เพื่อง่ายต่อการใช้งาน

# Create the parserparser = parsers.VOCBBoxParser(
annotations_dir=data_dir / "../train/Voc_annotation"#pathของไฟล์ voc,
images_dir=data_dir / "../train/Voc_annotation"#pathของไฟล์ภาพ)
# Parse annotations to create recordstrain_records, valid_records = parser.parse()
parser.class_map #เรียกดูclass
len(train_records), len(valid_records)#นับจำนวณtrain,valid

ขั้นตอนต่อไปคือการ augmentations หรือ การเพิ่มจำนวน dataset เพื่อให้โมเดลได้ train ข้อมูลที่เยอะมากขึ้น จากการ rotation, cropping, horizintal flips ภาพใน dataset เเละ ปรับขนาดรูปภาพของเรา

# Transforms
# size is set to 384 because EfficientDet requires its inputs to be divisible by 128
image_size = 384 train_tfms = tfms.A.Adapter([*tfms.A.aug_tfms(size=image_size, presize=512), tfms.A.Normalize()])
valid_tfms = tfms.A.Adapter([*tfms.A.resize_and_pad(image_size), tfms.A.Normalize()])
# Datasetstrain_ds = Dataset(train_records, train_tfms)
valid_ds = Dataset(valid_records, valid_tfms)

ถึงเวลาในการสร้างโมเดลเเละเลือกbackboneเเล้ว โดย icevision มีโมเดลเเละ backboneให้เลือกหลากหลายประเภทมากๆ คุณสามารถเลือกโมเดลเเละbackboneที่เหมาะสมกับโมเดลคุณได้เลย

model_type = models.mmdet.vfnet
backbone = model_type.backbones.swin_t_p4_w7_fpn_1x_coco
# Instantiate the model
model = model_type.model(backbone=backbone(pretrained=True), num_classes=len(parser.class_map))
# Data Loaderstrain_dl = model_type.train_dl(train_ds,batch_size=12,num_workers=4, shuffle=True)
valid_dl = model_type.valid_dl(valid_ds,batch_size=12,num_workers=4, shuffle=False)
metrics = [COCOMetric(metric_type=COCOMetricType.bbox)]
from icevision.metrics.confusion_matrix.confusion_matrix import *

ทำการ train โมเดลโดยใช้ fastai

learn = model_type.fastai.learner(dls=[train_dl, valid_dl], model=model, metrics=metrics)learn.lr_find()
# For Sparse-RCNN, use lower `end_lr`
# learn.lr_find(end_lr=0.005)

ครั้งนี้ผู้จัดทำได้ทำการ train 200 epochs เเละได้ค่า valley =1e-6(สังเกตได้จากผลลัพธ์ learn.lr_find())

นำค่าlearning rate ที่หาได้จากlearn.lr_find()เข้าไปใส่เเละเริ่มทำการ train model เลยยยย!

learn.fine_tune(200, 1e-06, freeze_epochs=1)

ทำการ save model(.pth)

from icevision.models import *# Save The Modelcheckpoint_path = 'swin-WB-checkpoint-full_s.pth'save_icevision_checkpoint(model,model_name='mmdet.retinanet',#ชื่อโมเดลที่ใช้backbone_name='swin_s_p4_w7_fpn_1x_coco',#ชื่อbackboneที่ใช้classes =  m.get_classes(),img_size=image_size,filename=checkpoint_path,meta={'icevision_version': '0.12.0'})

ผลลัพธ์ที่ได้จากการ train model

learn.metrics[1].metric.plot()
confusion Matrix

ผลลัทธ์ที่ออกมาถือว่าโอเคมากๆเลย จะเห็นได้ว่าโมเดลทายผิดค่อนข้างน้อย เเม้บางชนิดจะมีจำนวน dataset ค่อนข้างน้อยทำให้โมเดลสับสนไปบ้าง สำหรับ ตัว prediction จะเห็นได้ว่าถ้ารูปไหนมี white blood cell เกาะกลุ่มอยู่ใกล้ๆกันเเล้วละก็ โมเดลของเราจะไม่สามารถ detect ออกมาได้ หรือ detectได้ไม่ทั้งหมด

Model: icevision (Faster_rcnn)

เนื่องจากเราได้อธิบาย ตัว icevision ไปเป็นที่เรียบร้อยเเล้ว ครั้งนี้เราจะมาเปลี่ยนโมเดลกันบ้างเเต่เราจะใช้ icevision สุดเจ๋งที่เป็นlibary ขนาดใหญ่เหมือนเดิมโดยเราสามารถใช้codeคำสั่งที่กล่าวมาข้างต้นได้เลย! เพียงเเต่อย่าลืมเปลี่ยน model เเละ backbone เชียวว

# Installing IceVision 
# !pip install icevision[all] icedata

# Imports
from icevision.all import *
import icedata
# Load dataset
path = icedata.wb.load_data()
# Get the class_map, a utility that maps from number IDs to classs names class_map = icedata.pets.class_map() # parser: provided out-of-the-box
parser = icedata.wb.parser(data_dir=path, class_map=class_map) train_records, valid_records = parser.parse(data_splitter)
# shows images with corresponding labels and boxes show_records(train_records[:6], ncols=3, class_map=class_map, show=True) # Define transforms - using Albumentations transforms out of the box train_tfms = tfms.A.Adapter(
[*tfms.A.aug_tfms(size=384, presize=512), tfms.A.Normalize()]
)
valid_tfms = tfms.A.Adapter([*tfms.A.resize_and_pad(size), tfms.A.Normalize()]) # Create both training and validation datasets
train_ds = Dataset(train_records, train_tfms)
valid_ds = Dataset(valid_records, valid_tfms)

# Create both training and validation dataloaders
train_dl = faster_rcnn.train_dl(train_ds, batch_size=16, num_workers=4, shuffle=True)
valid_dl = faster_rcnn.valid_dl(valid_ds, batch_size=16, num_workers=4, shuffle=False)
# Create model
model = faster_rcnn.model(num_classes=len(class_map))
# Define metrics
metrics = [COCOMetric(metric_type=COCOMetricType.bbox)]
# Train using fastai2
learn = faster_rcnn.fastai.learner( dls=[train_dl, valid_dl], model=model, metrics=metrics )

learn.fine_tune(10, lr=1e-4)

ผลลัพธ์ที่ได้จากการ train model

Deploy Model

เมื่อเราได้สร้างโมเดลเป็นที่เรียบร้อยเเล้ว ถึงเวลาเเล้ว!! ที่จะส่งออกโปรเจกต์ของเราให้คนบนโลกได้ลองใช้งานจริง โดยผู้จัดทำได้ใช้ EC2 (Elastic Compute Cloud)จาก Amazon Web service ในการรันเว็บ เเละใช้ streamlit ออกเเบบเเละตกเเต่งหน้าเว็บสวยๆ

หน้าเว็บหลังจากdeploy(EC2เเละstreamlit)

เหตุผลที่ใช้ EC2 เนื่องจาก icevision ไม่สามารถ install ลง Windowsได้ค่ะเเละมีปัญหาอื่นๆเช่น stramlit cloud ไม่ลองรับ icevision เพราะเหตุนี้เราเลยจำเป็นต้องใช้ EC2 ในการ deployครั้งนี้ค่ะ T^T

หน้าเว็บหลังจากdeploy(EC2เเละstreamlit)

เพื่อนๆสามารถเข้าไปทดลองการทำงานของโมเดลได้เลยย เข้าไปที่ Select Activity>เลือก Detection>ใส่รูปภาพที่ Drag and drop file here

โมเดลจะ detect ออกมา บอกทั้งทั้งชนิดของclassเเละpersenconfidence

สามารถเข้าไปดูหน้าเว็บสวยๆได้ที่นี่ → deploy app

Baseline comparison

เมื่อนำผล Testset ที่ได้มาเปรียบกันระหว่าง model ทั้ง 3ตัว จะเห็นได้ว่า ชนิด Swintransformer ผลออกมาดีเลยทีเดียว

Testset Faster RCNN
Testset yolov5
Testset Swintransformer

สรุปจากผลจากโมเดลทั้ง 3 ชนิด จะพบว่า

Faster RCNN           — -> accuracy ≈ 33.53% , loss ≈ 66.5%
Yolov5 — -> accuracy ≈ 51.63% , loss ≈ 48.37%
Swin transformer — -> accuracy ≈ 56.37% , loss ≈ 43.62%

โมเดลSwin transformer มีความเเม่นยำอยู่ที่ 56 % จาก Testset ทั้งหมด 337 ภาพสามารถทายถูก 190 ภาพเเละ ทายผิด 71 ภาพ เเละมีอีก 76 ภาพที่โมเดลของเราไม่ detect ซึ่งพอไปตรวจสอบรูปภาพเหล่านั้นพบว่าส่วนมากจะเป็นรูป ที่มีปริมาณเม็ดเลือดเกาะตัวเป็นกลุ่มทำให้ โมเดลเกิดการสับสน เเละ detect ออกมาได้ไม่ครบถ้วนเเละเมื่อลองดูจากจำนวน dataset เเล้วจะเห็นได้ว่า

จำนวน Dataset ของ Promyelocyte มีจำนวนน้อยมากๆทำให้โมเดลสามารถ Train ได้น้อยเเละทายผิดอยู่บ้างค่ะ

Future plan

หลังจากที่เราได้ทำการสร้าง modelเสร็จเป็นที่เรียบร้อยเเละได้ทดลองdeployลงเว็บให้ทดลองใช้กันได้เเล้ว
ผู้จัดทำเล็งเห็นว่า อาจจะดีไม่น้อยถ้าเราสามารถพัฒนาโปรเจกต์ให้ดียิ่งขึ้นไปอีกเพื่อการนำไปใช้งานได้จริงในอนาคต จากการปรับปรุง Dataset โดยทำให้ dataset ที่มีอยู่ balanceกันมากขึ้นเเละทำการ improve modelให้ดียิ่งขึ้นจากการปรับจำนวน epoch ในการ train model ให้เหมาะสมกับmodelนั้นๆเพื่อลดการเกิด overfit เเละลองใช้ backboneเเละmodelชนิดอื่นๆให้มากยิ่งขึ้น ซึ่งถ้าโมเดลของเราพัฒนาไปถึงจุดที่ดีในระดับนึงเเล้ว ผู้จัดทำก็อยากจะพัฒนาตัว application ให้บุคลากรทางการเเพทย์ใช้ได้จริงตามโรงพยาบาลต่างๆค่ะ

อ้างอิง(Reference)

ทั้งหมดนี้เป็นเพียงส่วนเล็กๆในการนำ AI เข้ามาประยุกต์ใช้กับการเเพทย์เพื่อพัฒนาให้การรักษามีประสิทธิภาพมากยิ่งขึ้น เเม้ว่า AI จะสามารถทำนายได้อย่างเเม่นยำเเละรวดเร็วเเต่สิ่งสำคัญที่จะมองผ่านไม่ได้เลยนั่นก็คือความน่าเชื่อถือเเละประสบการณ์ของบุคลากรทางการเเพทย์ โดยมี AI เป็นฝ่ายสนับสนุนเพื่อประสิทธิภาพในการรักษาที่ดียิ่งขึ้น

project นี้จัดทำขึ้นภายใต้การดูเเลของโครงการ AI Builders 2022 ที่ช่วยสนับสนุน เเนะนำ เเละสอนให้เราสามารถพัฒนา AI เพื่อเเก้ปัญหาเเละนำไปประยุกต์ใช้ในชีวิตจริงได้

เเละขอบคุณการสนับสนุนเเละช่วยเหลืองานจากเพื่อนๆน้องๆทุกคน ในสังกัด Mysterious-hedgehogs ด้วยค่ะะ 😁

--

--