iDish the Food Nutrition Prediction: “การคาดการณ์ปริมาณสารอาหารจากภาพถ่ายอาหาร”

Parin Chiamananthapong
botnoi-classroom
Published in
4 min readSep 1, 2020

Team member: Pop 🏠, nnew 📊, ป๋ำ 🎭, โอ๊ต ⚙️, หมิว ✈️, นภันต์ 💻, เท็น 🏭, ภู 📡, กระติ๊บ 📈, ตุ๊ก 📚, โอ๋ 💾, Pui 📱

Objective: บทความนี้เป็นส่วนหนึ่งของ Data Science Essential ของ Botnoi Classroom หัวข้อ Machine Learning and Prediction Model

“Machine Learning” เรียกกันย่อๆ ว่า “ML” แปลตรงตัวคือ “การเรียนรู้ของเครื่องจักรกล” เพื่อจุดประสงค์ในการคำนวณหรือคาดการณ์ต่างๆ ลองนึกภาพหุ่นยนต์ที่สามารถตอบสนองการกระทำอย่างได้ เช่น ถามว่า “คุณคือใคร” เค้าก็จะตอบว่า “ฉันคือหุ่นยนต์น้อย (Botnoi)” หุ่นยนต์นี้ใช้ ML ในการประมวลผลเพื่อตอบคำถาม ถ้าเป็นเมื่อก่อนคงดูว่าล้ำยุคมากๆ แต่ปัจจุบันนี้ด้วยความสามารถของการประมวลคอมพิวเตอร์และปริมาณข้อมูลมหาศาลสามารถสร้างการเรียนรู้นี้ให้เกิดขึ้นได้ — สามารถศึกษาข้อมูลเบื้องต้นด้าน Machine Learning เพิ่มเติมได้จาก อะไรคือ การเรียนรู้ของเครื่อง (Machine Learning)?

รูปจาก https://www.thaiprogrammer.org/

บทความนี้เป็นส่วนหนึ่งในการทำโครงงานที่ 2 ของกลุ่มที่ 16 ในการเรียนรู้ใน Course Data Science Essential โดย Botnoi Consulting (สามารถติดตาม ผลงานโครงงานแรกของกลุ่มเราได้ที่ เงินซื้อความสุขได้ไหม และดัชนีค่าความสุขมาจากอะไรบ้าง — ส่งการบ้าน Project Week 1: Data Analytic) ในโครงการนี้เป็นการสร้าง Model สำหรับการทำ Machine Learning แล้วนำไปสร้าง API เพื่อการใช้งานแบบ web application ใน Platform ของ Botnoi โดยเราเลือกหัวข้อ iDish the Food Nutrition Prediction “การคาดการณ์ปริมาณสารอาหารจากภาพถ่ายอาหาร” ซึ่งจะเป็น application ที่ช่วยในการ track อาหารการกินในแต่ละวันของเรา เพื่อตรวจสอบปริมาณสารอาหารที่เราได้รับในแต่ละวัน และแนะนำเมนูที่เราควรกิน(หรือควรลด)เพื่อให้ได้ปริมาณอาหารในระดับที่เหมาะสม (อาจจะประยุกต์ในเรื่องอื่นๆเช่นการออกกำลังกาย ถ้ามีข้อมูลจากแหล่งอื่นๆเพิ่มเติม) ซึ่งใน feature แรกที่เราเลือกที่จะนำมา prototype คือ การคำนวณค่าสารอาหารจากรูปอาหารที่เราได้ถ่ายไว้ ซึ่งขั้นตอนกระบวนการสร้าง prototype จะมีดังนี้ครับ (ไฟล์ colab code ทั้งหมด สำหรับการ scrape, extract feature และ train model จะแนบไว้ที่ link ด้านล่างครับ)

Data science pipeline

  1. Get problem ตั้งปัญหาและรวบรวมไอเดียต่างๆ
  2. Data Collection การหาข้อมูลเพื่อทำการวิเคราะห์และสร้าง data set
  3. Data Cleaning การเตรียม และทำโครงสร้างข้อมูลเพื่อการทำ model
  4. Feature Extraction การแปลงข้อมูลเพื่อเปลี่ยนรูปในการทำ model
  5. Model Training and Test การแบ่งข้อมูลเพื่อการ train และ test model
  6. Evaluation การประเมินผลการทำ machine learning model
  7. Application Development การนำ model ที่ได้ไปประยุกต์ใช้งานกับ application
  8. Summary and Further Development สรุปผลการทำงานและการต่อยอดในอนาคต

Get problem

เริ่มต้นจากการประชุมเพื่อช่วยกันคิดว่าจะทำหัวข้ออะไรดี ซึ่งมีหลายแนวคิดที่น่าสนใจ เช่นเรื่องการพยากรณ์สภาวะอากาศในพื้นที่ต่างๆ เพื่อประโยชน์ในการวางแผนก่อสร้าง หรือ การพยากรณ์ราคาต้นทุนวัตถุดิบการเกษตรเพื่อวางแผนต้นทุนของร้านอาหาร แต่กลุ่มได้สรุปว่าจะทำ “การคาดการณ์ปริมาณสารอาหารจากภาพถ่ายอาหาร” โดยมีที่มาหลักจากในปัจจุบันผู้คนเริ่มที่จะสนใจในสุขภาพมากขึ้น ซึ่งสังเกตุได้จากการเข้า fitness, การเพิ่มขึ้นของผลิตภัณฑ์เพื่อสุขภาพ, etc. จึงอยากลองนำความรู้ machine learning ที่ได้จากการเรียนในคาบนี้ ไปประยุกต์กับอะไรบางอย่างที่เกี่ยวข้องกับสุขภาพดู จนได้ขอสรุปว่าเริ่มที่การ “กิน” ก่อนเพราะเชื่อว่าการกินเป็นการการดูแลสุขภาพที่ดีที่สุด จึงอยากเริ่มต้นที่จุดง่ายๆคือ web application ที่ช่วยคำนวณปริมาณสารอาหารจากรูปภาพอาหารที่เราได้ถ่ายไว้ครับ

Data Collection

เริ่มต้นจากการหาข้อมูลปริมาณสารอาหารในแต่ละเมนูอาหารไทย ซึ่งเราไปพบข้อมูลจากรายงานการศึกษาวิจัยปี 2551เรื่อง ปริมาณสารอาหารในอาหารจานเดียวที่จำหน่ายในกระทรวงสาธารณสุข (https://bit.ly/3gefziE) แต่เนื่องจากเอกสารนี้เป็น pdf จึงได้นำไปเข้าเว็บ online OCR (https://www.newocr.com) เพื่อดึงข้อมูล text จากในเอกสารออกมา แล้วนำไปใส่ใน google sheet ไว้ เพื่อใช้ในการอ้างอิงต่อไป ต่อมาเนื่องจากเราทำระบบที่บอกเมนูที่กินจากรูปอาหาร ดังนั้นเราจึงจำเป็นต้องเก็บรูปอาหารไทยจำนวนมาก ซึ่งตรงจุดนี้เราใช้ feature การ scrape ของ BotNoi sdk ที่ไปดึงรูปจาก Google Image Search มาบันทึกลง Google Drive เก็บไว้ครับ โดยเราจะเลือกเมนูจากไฟล์ pdf มาแบ่งให้กลุ่มละคน

ตัวอย่าง code ที่ใช้ในการ scrape รูป

Data Cleaning

เนื่องจากรูปภาพที่ scrape มาจะมีรูปที่ไม่เกี่ยวข้องเป็นจำนวนมาก (เช่นรูปหน้าคนขาย, รูปที่มีตัวอักษรทับ, หรือรูปที่ไม่เกี่ยวข้องเลยเช่น เครื่องบดขยะ) จึงต้องใช้แรงงานคนในกลุ่มมานั่งไล่คัดแยกรูปอีกที > < ซึ่งขั้นตอนนี้เป็นขั้นตอนที่ใช้เวลานานที่สุดและ(น่าจะ)เป็นขั้นตอนที่กินแรงเยอะที่สุดครับ ซึ่งสุดท้ายเราก็ได้รูปเมนูอาหารมาทั้งหมด 73 เมนู และรูปภาพทั้งหมด 3391 รูปครับ 🎉🎉🎉

หอยทอดจริงด้วย แต่ไม่ใช่ภาพอาหารอ่ะ > <

อันที่จริงเคยลองพยายามไป scrape ข้อมูลรูปภาพจาก wongnai เพิ่มเติมเพราะเป็นรูปที่มีคุณภาพสูง แต่ความหวังนี้ก็ได้ถูกหยุดไว้ด้วย hCaptcha ที่จะป้องกันการ scrape รูปจากเว็บอีกที (จริงๆอาจจะเป็นเพราะผมเปิดใน colab โดยใช้ headless selenium ก็เป็นได้)

Feature Extraction

ขั้นตอนนี้จะเป็นการเปลี่ยนแปลงรูปภาพที่เราได้ ไปเป็นข้อมูลในรูปแบบที่คอมพิวเตอร์เข้าใจ โดย model ที่ทีมเลือกใช้จะมีทั้ง 2 model คือ Resnet50 และ Mobilenet ซึ่ง Resnet50 จะมีความแม่นยำสูงกว่า แต่จะใช้เนื้อที่และกำลังในการประมวลผลมากกว่า ในขณะที่ Mobilenet จะใช้เนื้อที่น้อยกว่า (สามารถนำไปใส่ในอุปกรณ์ mobile ได้) แต่อาจจะมีความแม่นยำน้อยกว่า โดยตัวอย่าง code ที่ทำการแยก feature จะเป็นดังรูปครับ

Model Training and Test

ขั้นตอนต่อมา เราจะนำ feature ที่ได้จากข้อที่แล้ว มาป้อนให้ machine learning เพื่อ train ให้ระบบสามารถรู้ได้ว่าภาพไหนเป็นอาหารเมนูอะไร โดยเราได้แบ่ง data ไว้เป็น 2 ชุดคือ ข้อมูลสำหรับใช้ train และข้อมูลที่ใช้สำหรับ test (เพื่อทดสอบความแม่นยำของ model ที่เราได้ train ไว้) โดยกลุ่มเราได้เลือกใช้อัตราส่วนระหว่าง train:test ที่ 80:20 ครับ โดยเราจะใช้วิธี linearSVC ในการทำ Classification ครับ (สามารถดูรายละเอียดที่อธิบายเรื่องนี้เพิ่มเติมได้ที่ blog ของกลุ่ม 7 ครับ เขาเขียนไว้ดีมากเลย 😆)

ตัวอย่าง code สำหรับการ train model ครับ

Evaluation

จากการที่ได้ทดลองระหว่าง Resnet50 และ Mobilenet แล้วลองเก็บค่า accuracy ที่ได้จากชุดข้อมูล test จะได้ค่าดังนี้

ค่า accuracy ของ model resnet50 และ mobilenet

ซึ่งเราจะพบว่าตัว Resnet50 จะมีค่า accuracy มากกว่า Mobilenet แต่ไฟล์ feature ของ Resnet50 จะมีขนาด 784 KB ต่อไฟล์ ในขณะที่ Mobilenet จะมีขนาดที่ 8 KB ซึ่งมีขนาดเล็กกว่ามากเลยทีเดียว (อันที่จริงมีเก็บข้อมูลเวลาที่ใช้ในการทำ feature และ train ด้วย แต่พบว่าเวลาที่ใช้ในการ execute แต่ละรอบ ไม่ค่อยนิ่ง จึงไม่ได้นำมาใส่ในตารางนี้)

Application Development

ขั้นตอนหลังจากนี้ เราจะนำเอา model ที่ train เสร็จ มาหุ้มด้วย API อีกที ซึ่งในที่นี้ได้ใช้ Flask ในการทำ API และแบ่งนำไป host แยกไว้ 2 ที่ครับคือ

  • ตัว mobilenet จะ deploy ไว้ที่ Heroku ที่เป็น cloud platform สำหรับให้บริการ PaaS เจ้าหนึ่ง (คิดซะว่าคล้ายๆ App Engine ของ Google Cloud ครับ) และนำ API ที่ได้ไปฝากไว้ที่เว็บ OpenAPI ของ BotNoi อีกทีครับ (โดยตัวนี้จะทำหน้าที่เป็น API Gateway ที่เพิ่มเรื่องการ authen ด้วย JWT, มีการเพิ่ม rate limit, แชร์กับคนอื่นๆได้อีกทีครับ) โดยสามารถทดลองใช้ API ได้ที่ link ด้านล่างครับ
    https://openapi.botnoi.ai/dashboard/api/sa-food_predict
  • ตัว resnet50 จะ deploy ไว้ที่ VM ตัวเองบน DigitalOcean (เนื่องจาก model ตัวนี้มีขนาดใหญ่เกิน memory quota ที่ Heroku ตั้งไว้) แล้วตั้งไว้หลัง Kong ที่เป็น API Gateway อีกทีครับ

เมื่อเราได้ API แล้ว ต่อมาจึงได้ทำ web page ง่ายๆสำหรับใช้งานบนมือถือ เพื่อให้เราได้ทดลองถ่ายรูปอาหารไปลองเล่นได้ง่ายๆครับ 🍔🍔🍔

เย้ ทายถูกด้วย
ลองเอารูปอาหารฝรั่งใส่ดู กลายเป็นนำ้พริกกะปิ ปลาทู เฉย > <

Summary and Further Development

สุดท้ายแล้ว เราจะสรุปแบ่งออกได้เป็นใน 2 ด้าน คือ สิ่งที่ได้เรียนรู้ และแนวทางการต่อยอด project ต่อไปครับ

สิ่งที่ได้เรียนรู้เพิ่มเติม

  • model Resnet50 จะมีความแม่นยำสูงกว่า Mobilenet พอสมควร แต่โดยรวมก็ยังมีความแม่นยำตำ่อยู่ดี
  • จากการลองศึกษาเพิ่มเติม ทำให้รู้ว่าการแยกภาพอาหารถือเป็นหัวข้อที่ยากมากเรื่องนึง เนื่องจากมีเมนูจำนวนมาก และในเมนูเดียวกันก็อาจจะมีความหลากหลายอีกต่างหาก (ซึ่งบางรูปขนาดใช้คนแยกยังยากเลย) ซึ่งในงานวิจัยที่พบเขาใช้รูปเป็นหลักแสนเลยทีเดียว 😅
    https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6883229/#!po=3.12500
  • ทางทีมได้มีการทดลองนำเทคนิค Augmented มาใช้กับรูปเพิ่มเติม (คือนำรูปมาตัดบางส่วน, หมุนเปลี่ยนด้าน, etc.) ซึ่งได้นำมาทำ feature แล้ว แต่ยังไม่ได้ train model เพราะใช้เวลา train นานเกินไปจน colab ปิดตัวเองไป (ถ้าจำไม่ผิด นานมากกว่าชั่วโมงครึ่งนะ)
  • งานการ clean data เป็นงานที่ใช้เวลาและแรงงานนานที่สุดใน project นี้ ซึ่งเราอาจจะลดเวลาในส่วนนี้ลงได้บางส่วน เช่น การซื้อ data จาก provider ที่เชื่อถือได้ หรือการสร้าง platform เพื่อมาเก็บ data เพิ่มเติมจาก user (เช่น Shopee ที่ให้ user พิมพ์รายละเอียดข้อมูลต่างๆทุก field เทียบกับสลิปที่ได้ upload ไว้ด้วยอีกที หรือ Google Recaptcha ที่ให้ user ช่วย label รูปไปในตัว)
  • จากการทดลอง มีความรู้สึกว่า spec เครื่อง colab ที่ได้อาจจะมีความไม่แน่นอน (บางครั้งไว บางครั้งก็ช้า) ดังนั้นถ้าเราทำ product ที่เกี่ยวข้องกับ machine learning จริงๆ ก็อาจจะย้ายไปเลือกใช้ cloud product ตัวอื่นๆที่มีความเหมาะสมมากกว่า

แนวทางการต่อยอด

  • ใส่รูปอาหารที่กินในแต่ละวันจากนั้นนำพลังงานมาเปรียบเทียบกับค่า TDEE (ผลรวมของพลังงานที่ร่างกายใช้ในแต่ละวัน) เพื่อดูว่าพลังงานเพียงพอไหมในแต่ละวัน
  • นำไปคำนวณพร้อมกับค่า BMI เพื่อหาจำนวนพลังงานที่เหมาะสมต่อการใช้งานในแต่ละวัน เช่น การใส่ข้อมูล ส่วนสูง น้ำหนัก หรือสภาวะที่จำเป็นอื่นๆ ในการหาความต้องการพลังงานที่เหมาะสม
  • ทำ meal plan สำหรับคนควบคุมอาหาร
  • ต่อยอดเป็น application ที่ช่วยคนที่ต้องควบคุมอาหาร เมื่อถ่ายภาพ จะสามารถระบุว่าอาหารจานนี้เหมาะกับผู้ใช้หรือไม่ based on personal info ที่ให้และความต้องการสารอาหารตามช่วงวัยและ lifestyle (ผู้สูงอายุที่มีโรคประจำตัว ต้องลดบางอย่างต้องเพิ่มบางอย่างเช่นแคลเซียม หรือคนออกกำลังกายต้องการโปรตีน)
  • ให้ user ใส่ข้อมูลเพิ่มเช่น แต่ละเมนูมีส่วนประกอบหลักอะไรบ้าง ก็อาจช่วยผู้ใช้ให่รู้ได้ว่ามีส่วนประกอบของอาหารที่ตนเองแพ้หรือไม่ เช่น คนที่แพ้ถั่ว แพ้สับปะรด (บางทีอาหารไทยก็เครื่องเยอะ ถ้ารู้พวกนี้ได้ก็จะช่วยได้มากขึ้น)
  • ถ้าเราสามารถได้ข้อมูลจากแหล่งอื่นๆเพิ่มเติม (เช่น FitBit) ก็อาจจะแนะนำในเรื่องอื่นๆเพิ่มเติมได้ เช่น การออกกำลังกายที่เหมาะสมสำหรับพฤติกรรมการกินและการใช้ชีวิตของแต่ละคน

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

--

--

Parin Chiamananthapong
botnoi-classroom

POS (Plain Old Full-Stacked) Developer who loves coding, startup, blockchain and anime :D