ปลาอะไรเอ่ย? แชทถาม Fish Tank Bot ดูสิ

Teddy Sangtongdee
botnoi-classroom
Published in
5 min readMar 6, 2021
Credit: Unsplash/@tb_motivv

Highlights of this project

  • Brainstorm : การแก้ไขปัญหาเมื่อไปเที่ยวทะเล หรือ aquarium แล้วไม่รู้ว่าปลาชนิดนี้เรียกว่าอะไร
  • Get data: ดึงข้อมูลแบบ Scrape image มาใช้ทำนายว่าชนิดของปลา
  • Build the model and deploy on Heroku: สร้าง model เพื่อทำนายผลด้วย Logistic regression
  • Chatbot: เพื่อการใช้งานง่าย เราเชื่อมโยง API เข้ากับ LINE chatbot
  • Prediction model: เรียกใช้ API ที่ฝากไว้กับ Heroku ให้ประมวผลตัว model ได้สะดวกและแสดงผลได้ทันที
  • Results: ผลการทำนายชื่อและรูปปลาผ่าน model ให้ความเชื่อมั่นต่อผู้ใช้

Brainstorm

Fish Tank Bot — ตู้ปลาบอท / บอทปลาตู้ แล้วแต่จะเรียก

การเลือกหัวข้อที่จะมาทำ Image classification ทางกลุ่มเราได้ทำประชุมร่วมกัน โดยมีเพื่อนในกลุ่มเสนอเรื่องเกี่ยวกับตอนไปเที่ยว aquarium แล้วอยากรู้ว่าปลาที่เราเห็นตอนนี้คือปลาอะไร โดยทางกลุ่มเราจะทำแชทบอทเพื่อทายชื่อปลาใน aquarium กัน

คอมพิวเตอร์วิทัศน์ (computer vision) เป็นพื้นฐานของแชทบอทนี้ เป้าหมายคือการ classify รูปที่รับจาก chatbot แล้วบอกว่า ปลานี้คือปลาอะไรกันนะ แค่มีบอทตัวนี้เราก็ไป aquarium ได้อย่างคูลๆ ถ้าแฟน (หรือลูก) ถามว่านี่ปลาอะไร ก็ยิ้มใสๆถ่ายรูปส่งให้บอทตอบได้เลย

ขั้นตอนดำเนินโปรเจ็คมีง่ายๆ ตามนี้

  1. Get data and preparation
  2. Build and deploy model
  3. Create chatbot

Section 1: Get data and Preparation

ในตอนนี้จะพูดถึงการเตรียมข้อมูลกันก่อน อันนี้เป็นขั้นตอนสำคัญขั้นตอนนึงในการทำ machine learning เลย คือการหา dataset เพราะ bot จะรู้จักชื่อปลาได้ ก็ต้องได้รับการ train จากข้อมูลที่เราป้อนให้ ในที่นี้เป็นการเรียนแบบที่เรียกว่า “supervised learning” คือ เราต้องสอนโดยเอาภาพให้ดูแล้วบอกว่า นี่คือปลาอะไร (label) เมื่อเรียนรู้ไปเรื่อยๆ model ของเราก็จะสามารถเรียนรู้จนทายชื่อปลาได้

***ของฝากผู้อ่าน *** สำหรับคนที่สนใจเรียนงานด้าน machine learning พวกเรามีที่แห่งหนึ่งที่สามารถไป download เอา dataset มาได้เลย นั่นคือ “Kaggle” เว็บนี้ดีมากจริงๆ มีทั้ง dataset และโจทย์ที่ให้เรียนรู้มากมาย ทางเราได้ download รูปมาจาก Kaggle มาสำรวจกันแล้ว ปรากฎว่าข้อมูลปลามีถึง 400 กว่า species เลยทีเดียว

แต่ๆๆ รูปที่ใช้ในการ train แต่ละ species มีเพียงแค่ 5–10 รูปเท่านั้น ซึ่งมันน้อยมากกกกก เราต้องขุดกันต่อ เลยไปจบกันที่ scrape รูปกันเอาเอง (สนใจเทคนิค web scraping อยู่เหรอ? ลองไปอ่านบทความนี้สิ)โดยเราอ้างอิง list ปลาจากเว็บ Build Your Aquarium โดยเราเริ่มต้นจากการทำ web scraping ดึงรูปมา 100 รูปต่อปลาหนึ่งชนิด และบันทึกไว้เป็น file .jpg เพื่อนำไปใช้งานและการ clean ที่ง่ายขึ้น

สังเกตการวาง folder อันนี้เป็นท่ามาตรฐานที่นิยมใช้ คือสร้าง folder ตามชื่อ label แล้ว ใส่รูปตาม label ลงไป

ดาวน์โหลดภาพมาไว้ในเครื่องของพวกเรา
อัพโหลดภาพกลับไปรวมไว้ที่ กูเกิลไดร์ฟ
ทำบัญชี index ชื่อปลาไทยและอังกฤษให้อยู่ในแบบตาราง กูเกิลสเปรตชีต

Colab#1: Get fish images เมื่อทำการรันโค๊ดนี้ด้วยบัญชีกูเกิล แค่นี้ data ก็พร้อมใช้แล้ว เหนื่อยกันหรือยัง? งั้นไปต่อกับการ Build model กันเลย

Section 2: Build and deploy model

เรามาถึงขั้นที่สอง ตอนนี้เราจะพูดถึงการสร้าง model และทำเป็น API กัน ก่อนอื่นต้องบอกก่อนว่าเราใช้ library บางตัวของ botnoi ดังนั้นจึงต้องมีการ install library ก่อนเรียกใช้ และในบทความนี้เราจะเล่าถึง code จุดที่สำคัญๆเท่านั้น สำหรับผู้สนใจ ดูโค๊ดตัวเต็มกันทั้งสองตัวได้ที่นี่: Colab#2: Build model และ Colab#3: Predict model

หลักการทำงานของทั้งสองไฟล์ข้างต้นนั้น แบ่งออกเป็น 4 ส่วนคือ Extract Feature, Train Model, Prepare API for prediction, และ Deploy ML model

ลองเรียกใช้ API โดยตรงผ่านบราวเซอร์

ขั้นตอนที่ 1 Extract Feature

เนื่องจากในรูป 1 รูปจะมีการเก็บข้อมูลตัวเลขอยู่จำนวนมาก เราจะต้องมีการคัดคุณสมบัติที่สำคัญที่ใช้แยกแยะรูปออกมา ในขั้นตอนนี้เราจะใช้โมเดลที่ได้รับฝึกฝนมาแล้ว ภาษาคอมเรียกกันว่า Pre-trained Model

เจ้าโมเดลที่เรียนรู้มาแล้ว แบบนี้คืออะไรกันนะ? มันเกิดจากแนวคิดการลดเวลาและทรัพยากรที่ต้องมาเริ่มนับหนึ่งใหม่ในการพัฒนาโมเดล สำหรับแนวคิดที่ว่านี้คือ Transfer learning … ใช่แล้ว! คอมพิวเตอร์เวลามันเรียนรู้เสร็จจากปัญหาเรื่องหนึ่ง มันก็มีความสามารถในการถ่ายทอดต่อกันไปได้ แล้วก็เด็ดเลเยอร์ตัวสุดท้ายออกที่เรียกว่า Classifier แล้วนำตัวแปร Y หรือ Label ของเรามาทดแทน จากนั้นก็ฝึกฝนโมเดลที่มีเลเยอร์สุดท้ายเป็นของเราด้วยทรัพยากรคอมพิวเตอร์ที่เรามี

การเลือกโมเดลกึ่งสำเร็จรูป (คำเรียกของผู้เขียน) ก็เป็นเรื่องหนึ่งที่ต้องพิจารณา ลองดูรายชื่อโมเดลที่พร้อมใช้ของ Keras จะพบว่าตัวเลือกมีให้เยอะมาก แต่ควรพิจารณาสองสิ่งอันดับแรกคือ ขนาด (size) และความแม่นยำ (accuracy)

Available models in Keras Application (source: https://keras.io/api/applications/)

แล้วโปรเจ็คของเราเลือกตัวไหนล่ะ? เป็นคำถามที่ดี เนื่องจากเป็นงานโปรดักชั่นที่มีสเกลเล็ก จึงตัดสินใจจิ้มไปที่ MobileNet (จริงๆ ครูบอทน้อย แนะนำสำหรับผู้เริ่มต้น) แล้วเรามาทำการคัดแยกคุณสมบัติเด่นหรือเรียกว่า extract feature ของรูปปลาออกมา ทั้งหมดทั้งมวลนี้เป็นการเตรียมข้อมูลเบื้องต้นก่อนเข้าสู่การฝึกฝนหรือ train

เรามีเหตุผลเหมือนกัน สาเหตุที่เลือกใช้ MobileNet แทน RestNet50 เพราะข้อจำกัดของ Heroku server ที่ memory ไม่พอ (บัญชีฟรี แต่ไม่ใช่ฟรีเมี่ยมนะ) เขามีให้ใช้เล็กน้อยแค่ 500 MB เท่านั้นเอง …ลองคิดดู ถ้าหลงไปโหลดเจ้าโมเดลที่ชื่อ VGG19 เข้าไป โดยหลงใหลกับจำนวนพารามิเตอร์ที่เธอถูกฝึกมา ซึ่งขนาดตัวเธอนั้นก็อวบเสียเหลือเกิน (549 MB) หากเป็นเช่นนั้น พวกเราคงต้องนั่งเติมตังค์ให้กับคุณเฮ (Heroku) ไปไม่น้อยแน่ๆ

โค๊ดเรียกใช้ MobileNet

หลังจากนั้น เราก็เอา feature ที่ได้มาใส่ dataset ดังนี้

โค๊ดเรียก features ที่ได้มาใช้กับ dataset

ขั้นตอนที่ 2 Train model

เรากำลังจะสร้าง Machine Learning (ML) model ด้วยการแบ่งข้อมูลที่มาอยู่เป็นสองส่วนโดยใช้ library scikit-learn เป็นหลัก ก่อนที่จะ train model ต้องแบ่งข้อมูลเป็นสองส่วนก่อน โดยข้อมูลกลุ่ม train จะใช้สำหรับ train model และ test มีไว้เพื่อทดสอบความแม่นยำของ model เราจะได้รู้ว่า ML model ของเรามีประสิทธิภาพขนาดไหน และในโจทย์นี้เราเลือกใช้ Logistic Regression เนื่องจากเป็น model ที่มีขนาดเล็กและสามารถทำนายออกมาเป็นความน่าจะเป็นของ class นั้น ๆ ได้ ซึ่งจะนำค่าความน่าจะเป็นที่ทำนายได้ไปใช้กับ chatbot ต่อไป

ปกติแล้ว Logistic regression จะทำนายได้แค่ binary classification (นั่นคือทำนายว่าใช่หรือไม่ใช่) การที่จะทำนายมากกว่า 2 class หรือ multi-class นั้น เรากำหนดพารามิเตอร์ multi_class=’multinomial’ ใน Logistic Regression เพื่อให้สามารถใช้ทำนาย multi-class ได้แบบที่สร้างเพียง 1 model โดยมี output ของการทำนายเป็นความน่าจะเป็นของทุก ๆ class (Credit : Multinomial Logistic Regression With Python (machinelearningmastery.com)

จากนั้นเราทำการ train model ด้วยข้อมูลจาก dataset

โค๊ดสำหรับ fitting model ด้วย dataset ที่เรามี

ขั้นตอนที่ 3 Prepare API for prediction

หลังจากที่เราสอน (train) โมเดลและให้ลองทำแบบทดสอบ (test) กันไปจนเป็นที่พอใจแล้ว เรามาทำการเริ่ม predict รูปกัน ส่วนนี้เป็นการนำรูปมาสกัดคุณสมบัติ (feature extraction) ผ่าน mobilenet โดยการนำรูปมาแปลงเป็น pickle file ก่อน แล้วนำ model ที่ train ในขั้นตอนที่ 2 มาใช้งาน

ก่อนอื่น มาดูกันก่อนว่ารูปที่นำมาใช้ predict นั้นเป็นอย่างไร

Ig_89799_Assorted_Ryukin.jpg (liveaquaria.com)

ผลลัพธ์ออกมาเป็นน้องปลาทอง (Gold Fish) นั่นเองทีนี้ลองมาดูกันว่า model ของเราจะทำนายน้องปลาทองได้ถูกหรือไม่ จาก code ด้านล่างนี้

โค๊ด prediction เรียกใช้โมเดลที่เป็นไฟล์ pickle

ผลที่ได้คือ (‘Tiger Barb’, 0.051659378907687514)

Tiger Barb คืออะไรกัน ไม่นะ ทำนายผิดหรือนี่ นอกจากนี้ยังให้ค่า probability ที่ต่ำมาก เพียง 5 % แสดงว่าตัวโมเดลก็ไม่มั่นใจในคำตอบนี้ด้วยสิ สาเหตุที่ model ไม่แม่นเพราะเราใช้ moblienet ซึ่งให้ผลทำนายไม่ดีเท่า resnet50 แต่เพราะข้อจำกัดของ server เราจึงต้องการ model ขนาดเล็กนั่นเอง

หลักจากได้ model มาแล้ว เราจะทำการ deploy บน Heroku ซึ่งเป็น server ที่เราสามารถวาง API ตัวย่อมๆได้ฟรี ใครที่ไม่เคยใช้ Heroku ลองดูเพิ่มเติมได้ที่บทความนี้

ข้อผิดพลาดที่ควรระวังเมื่อรันโค๊ดบน Heroku เนื่องจากข้อจำกัดของบัญชีฟรี

ขั้นตอนที่ 4 Deploy model

เราจะทำการ deploy model เข้า Heroku ซึ่งเป็น server ที่เราสามารถวาง API ตัวย่อม ๆ ได้ฟรี ใครที่ไม่เคยใช้ Heroku ลองดูเพิ่มเติมได้ที่ ตัวอย่างการสร้างและ host AI API บน Heroku และ BOTNOI OpenAPI | by Dr. Winn Voravuthikunchai | botnoi-classroom | Medium

เพื่อให้ผลลัพธ์ออกมาตรงตามที่ต้องการ เราได้ปรับเปลี่ยน code ในส่วนที่ใช้ model จากตัวอย่าง link ด้านบนเล็กน้อย โดยมี code ดังนี้

โค๊ดสำหรับ mapping ตัวเลขความน่าจะเป็นให้เป็นข้อความ

จากฟังก์ชันด้านบน เราปรับค่าความน่าจะเป็นให้กลายเป็นคำพูดของ chatbot โดยปรับคำพูดจากความน่าจะเป็นที่ model ทำนายได้นั่นเอง โดยกำหนดว่าถ้าความน่าจะเป็นที่ได้น้อยกว่า 7 % นั่นคือ model ทำนายผลโดยที่ไม่แน่ใจคำตอบ แต่ถ้าได้ความน่าจะเป็นระหว่าง 7–9 % นั่นหมายความว่า model ค่อนข้างมั่นใจในคำตอบ แต่ถ้าได้ตั้งแต่ 9 % ขึ้นไป แสดงว่า model มั่นใจในคำตอบมาก ๆ นั่นเอง บางคนอาจจะสงสัยว่าทำไมถึงกำหนดช่วงความน่าจะเป็นแบบนี้ ก็เพราะว่าเกิดจากการสังเกตผลการทำนายของ model นั่นเอง ฮ่า ๆๆ

แค่นี้ API ก็พร้อมใช้งานแล้ว ตอนต่อไปเรามาเตรียม chatbot เพื่อเรียกใช้กัน

Section 3: Chatbot

เชิญเพิ่มน้องปลาตู้เป็นเพื่อนไลน์ได้ที่ไอดี @152uwmii

หลังจากที่เราได้ API ตัวทายชื่อปลามาแล้ว เราก็จะมาสร้าง chatbot กัน โดยเราเริ่มจากการ flow การคุยของ bot ซึ่งการทำงานของ bot เรา สามารถทำงานได้ 2 route อย่างแรกคือการใส่รูปปลาใน chatbot bot จะทำนายว่าเป็นปลาชนิดไหน อย่างที่สองคือ เรารู้ชื่อปลาแล้ว แต่อยากรู้ว่ามันหน้าตายังไง มีข้อมูลเบื่องต้นอะไร เพียงแค่เราพิมพ์ชื่อปลาเป็นภาษาไทย หรือ อังกฤษ bot จะแสดงรูปปลาพร้อมข้อมูลเบื่องต้น นี้คือรูปที่แสดง flow chatbot โดยรวมซึ่งทำบน miro

เราก็จะสร้าง chatbot กันโดยใช้ BotNoi SME Tool สำหรับคนที่ไม่เคยใช้มาก่อนวิธีใช้โดยละเอียด ดูเพิ่มเติมได้ที่นี่ ตรงนี้เราจะขอพูดถึงการขั้นตอนคร่าวๆ คือ “เชื่อมต่อกับไลน์” และ “เขียนไดอะล็อกในบอทน้อยทูล”

“ค้นหาปลาด้วยชื่อ” เป็น route ขาแรกในการเรียกใช้บอทโดยยูสเซอร์

ขั้นตอนที่ 1 การออกแบบ

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

1. “หารูปจากชื่อ” ใช้สำหรับกรณีที่บริเวณตู้ปลามีชื่อปลาบอกแต่ไม่มีการระบุหน้าตา ทำให้บางครั้งเราจะไม่รู้ว่าปลาชื่อนี้มีลักษณะอย่างไร จึงออกแบบให้สามารถหารูปภาพปลาจากชื่อพร้อมข้อมูลเพิ่มเติมได้

2. “หาชื่อจากรูป” เป็นประเภทของการใช้งานที่ได้มาจาก API ในหัวข้อก่อนหน้าเพื่อตอบโจทย์การหาชื่อปลาที่อยู่ในรูปนั้น ๆ

ถัดมาหลังจากการกำหนดการใช้งานแล้วก็มาถึงขั้นตอนในการออกแบบ flow การทำงานของ chatbot ซึ่งทางกลุ่มได้ออกแบบมาเป็น flow การทำงาน 2 สายคู่กันดังภาพด้านล่าง

Dialog flow หรือการไหลของบทสนทนาของเจ้าบอทปลาตู้

ขั้นตอนที่ 2 การเตรียมข้อมูล

ในส่วนของการเตรียมข้อมูลเนื่องจากใน flow การทำงานจะมีการเรียกข้อมูลของปลามาแสดงใน 2 ขั้นตอน คือ 1. ขั้นตอนการให้ชื่อปลาแล้วเรียกรูปภาพปลา 2. ขั้นตอนการเรียกข้อมูลเพิ่มเติม ทางกลุ่มจึงเลือกที่จะสร้าง spreadsheet สำหรับเก็บข้อมูลแล้วใช้ API ในการเรียกข้อมูลมาใช้ตามต้องการ ซึ่งมีลักษณะ sheet ตามภาพด้านล่าง

ตารางข้อมูลสำหรับ API ค้นหาด้วยชื่อปลา

ขั้นตอนที่ 3 การสร้างแชทบอท

หลังจากสร้างบัญชีไลน์ official ที่มาจากเว็บสำหรับนักพัฒนาแอพพลิเคชั่นไลน์ ทางกลุ่มก็ได้นำมาเชื่อมต่อกับ BOTNOI SMEs ซึ่งเป็นเครื่องมือในการจัดการระบบและบริการหลังบ้านของแชทบอทฝีมือคนไทย ประสิทธิภาพและรูปแบบการทำงานตอบสนองต่อผู้ใช้คนไทยอย่างมาก หากใครคุ้นเคยก็ขอให้นึกถึง Google Dialogflow

จากนั้นจึงทำการเชื่อมต่อขั้นตอนของ chatbot ให้เป็นไปตาม flow ที่ออกแบบไว้ ซึ่งสุดท้ายได้ chatbot ในชื่อของ ตู้ปลาบอท (จริงๆ เรียกอีกชื่อก็เก๋ดีนะ น้องปลาตู้) ตามไอดีไลน์ @152uwmii มีตัวอย่างการใช้งานดังภาพต่อไปนี้

ผลลัพธ์ของบทสนทนากับบอทที่ถูกสอบถามด้วยชื่อปลาและรูปภาพปลา

เมื่อเรียบร้อยก็จะได้บอทหน้าตาแบบนี้ ถามตอบข้อมูลปลาได้เลย

สแกน QR code เพื่อเพิ่มน้องปลาตู้เป็นเพื่อน

บทสรุป

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

Fish Tank Bot — น้องปลาตู้ ตั้งอยู่บนสมมติฐานที่อยากรู้ว่า “ปลาอะไรกันนะที่มันว่ายอยู่หน้าเรา” เมื่อตั้งเป้าหมายได้ชัด ถัดมาคือ “ข้อมูล” ที่ต้องมีการจัดระเบียบและจำนวนเพียงพอสำหรับสอนคอมพิวเตอร์ เราคาดหวังให้มีโมเดลการเรียนรู้ที่ให้คำตอบเป็นชื่อปลาหรือรูปปลาที่ใกล้เคียงกับคำถามที่เราป้อนไปยังแชทบอท

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

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

ส่งท้าย

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

ขอขอบคุณผู้ร่วมเดินทางในครั้งนี้: Aon, Cherry, Maw, Nob, Oo, Path, Tarit, Teddy, Vin และเหล่าสมาชิกของกลุ่ม BN-CVE for FUN#5 และที่ขาดไม่ได้เลยทีมงานคุณภาพของ ดร.วิน ผู้ก่อตั้ง/ซีอีโอของบอทน้อย พร้อมทั้งอาจารย์และเจ้าหน้าที่ทุกท่าน

--

--