บทนำ
ระวังนะน้อง!
บทสอนนี้สำหรับ AIfES เวอร์ชั่น 2.0.0 เท่านั้น บทสอนเวอร์ชั่นใหม่หาดูได้ในลิงก์ที่อัพเดทแล้ว.
AIfES ทำงานร่วมกับเฟรมเวิร์ก ML เกือบทุกตัวเลย ไม่ว่าจะเป็น TensorFlow, Keras หรือ PyTorch แต่ก็มีคนถามบ่อยๆ ว่า เออ... แล้วเราเอา AIfES ไปรันบน PC เพื่อพัฒนา Artificial Neural Networks (ANN) ให้ง่ายขึ้น หรือเพื่อเทรนเน็ตเวิร์กใหญ่ๆ ก่อนจะเอาไปรันบนบอร์ด Arduino ได้มั้ย?
คำตอบคือ: ได้สิว่ะ 😃
ในบทสอนนี้เราจะใช้ IDE ฟรีอย่าง Code::Blocks ที่เป็น C/C++ แบบโอเพ่นซอร์ส
เรื่องการเทรน ANN บนบอร์ด Arduino โดยตรงด้วย AIfES นั้น เราเคยสอนไปแล้วในบทสอนก่อนหน้านี้
ในบทสอนนี้เราจะโชว์ให้ดูว่า:
- ติดตั้ง AIfES ใน Arduino IDE ยังไง
- นำเข้า AIfES เข้าโปรเจกต์ Code::Blocks ยังไง
- เทรน ANN บน PC ด้วย AIfES ยังไง
- ดึงค่า weights ออกมายังไง
- เอา ANN ขึ้นบอร์ด Arduino ของนายยังไง
ความเข้ากันได้ของ AIfES
เพราะว่า AIfES ถูกเขียนด้วยภาษา C ล้วนๆ ดังนั้นซอร์สโค้ดของไลบรารี AIfES for Arduino จึงสามารถใช้ได้กับฮาร์ดแวร์เกือบทุกชนิด ด้วยเหตุนี้ AIfES ก็ควรจะรันได้บนบอร์ด Arduino หรือบอร์ดที่เข้ากันได้เกือบทุกตัวเช่นกัน ส่วนตัวเร่งความเร็วเฉพาะฮาร์ดแวร์อย่าง Arm CMSIS ต้องเปิดใช้งานในไฟล์ aifes.h มีตัวอย่างให้ดูได้ในลิงก์ที่อัพเดทแล้ว
ซอร์สโค้ดของไลบรารี AIfES for Arduino ยังสามารถรันบน PC ได้อีกด้วย โดยคอมไพเลอร์/ฮาร์ดแวร์ต้องเข้ากันได้กับ GCC
ข้อดีของมันคือ เราสามารถเทรนเน็ตเวิร์กใหญ่ๆ บน PC ล่วงหน้าได้ และซอร์สโค้ดก็ตรงกับที่ใช้บน Arduino เลย ทำให้การย้ายโค้ดไปมาไม่มีปัญหา อีกทั้งเรายังสามารถออกแบบโครงสร้าง ANN บน PC ก่อน แล้วค่อยเอาไปใส่ใน Arduino IDE อีกที ซึ่งเหมาะมากสำหรับระบบที่เรียนรู้ได้ด้วยตัวเอง
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ AIfES ไปหาอ่านกันได้ที่เว็บไซต์หลักของโครงการ
ติดตั้ง AIfES ใน Arduino IDE
เพื่อให้ทำตามตัวอย่างได้ นายต้องดาวน์โหลดและติดตั้ง AIfES (ค้นหาคำว่า aifes) ผ่าน Arduino Library Manager ให้เรียบร้อยก่อน
ตัวอย่างที่ใช้
สำหรับบทสอนนี้ เราจะใช้ตัวอย่างที่มีอยู่แล้วในไลบรารี AIfES นั่นคือการจำลองและเทรนเกต XOR ด้วย ANN ตารางความจริงของ XOR แสดงอยู่ในภาพด้านล่าง

โครงสร้าง ANN ที่ใช้สำหรับการจำลองแสดงอยู่ในภาพด้านล่าง ฟังก์ชัน sigmoid ถูกใช้เป็น activation function ใน ANN ทั้งหมด

เราได้ใส่ตัวอย่าง XOR หลายตัวไว้ในไลบรารี AIfES ซึ่งควรจะรันได้บนบอร์ดทุกชนิด
นี่คือวิธีหาตัวอย่างที่มีโครงสร้าง ANN แบบนี้ใน Arduino IDE ของนาย:
File -> Examples -> AIfES for Arduino -> 0_Universal -> 0_XOR
0_XOR_Inference
- ตัวอย่างนี้ทำแค่ Inference (การอนุมานผล) เท่านั้น น้ำหนัก (weights) ถูกเทรนไว้แล้ว
1_XOR_training
- ตัวอย่างนี้จะทำการเทรนโมเดลบนบอร์ด Arduino เลยจ้า
4_XOR_Inference_keras
- ตัวอย่างนี้เทรนโมเดลใน Keras ก่อน แล้วค่อยย้ายน้ำหนัก (weights) มาใช้ใน AIfES
ในบทสอนนี้ เราจะเทรน ANN บน PC ด้วย AIfES แล้วปริ้นท์น้ำหนักที่ได้ออกมา จากนั้นก็ไปสร้าง ANN แบบเดียวกันบนบอร์ด Arduino ด้วย AIfES แล้วก็ใส่ค่าน้ำหนักที่ได้เข้าไป พอเสร็จแล้วก็รัน Inference บนบอร์ดได้เลย ง่ายมั้ยล่ะ!
สเก็ตช์ที่เหมาะกับงานนี้ก็มาจากตัวอย่าง 4_XOR_Inference_keras นั่นแหละ ตัวอย่างนั้นเทรนใน Keras, พิมพ์น้ำหนักออกมา แล้วก็เอาไปใส่ในสเก็ตช์ เราก็หยิบสเก็ตช์จากตัวอย่างนั้นมาใช้ได้เลย
ส่วนการเทรนใน AIfES ก็มีตัวอย่างที่เหมาะเจาะอยู่แล้ว คือ 1_XOR_training เราปรับโค้ดตัวอย่างให้เป็นโครงสร้าง C แบบคลาสสิกที่มีฟังก์ชัน main() ฟังก์ชัน Arduino Sketch ทั่วไปอย่าง setup() หรือ loop() ก็ตัดทิ้งไปเลย แล้วก็เปลี่ยน Serial.print() เป็น printf() แบบธรรมดา จุดที่ต่างที่สุดคือตอนจบโปรแกรมจะพิมพ์ค่าน้ำหนักออกมา ปกติตัวอย่างนี้ใช้เทรน ANN บนบอร์ดโดยตรงแล้วรันเลย แต่คราวนี้เราจะเทรนบน PC แล้วให้โปรแกรมพิมพ์น้ำหนักออกมาทาง printf() จากนั้นก็คัดลอกน้ำหนักไปแปะใน Arduino Sketch อีกที ซอร์สโค้ดสำหรับการเทรนอยู่ในโปรเจกต์นี้แล้วในชื่อไฟล์ main.c นะจ๊ะ
Integrate AIfES in Code::Blocks
ขั้นต่อไปคือสร้างโปรเจกต์ใน Code::Blocks แล้วก็ติดตั้ง AIfES เข้าไป ตามมาเลย!
เตรียมตัวก่อน:
- ดาวน์โหลด Code::Blocks IDE แล้วติดตั้งให้เรียบร้อย (เคล็ดลับ: ดาวน์โหลดเวอร์ชันที่มีคำว่า "mingw" อยู่ เพราะมันมีคอมไพเลอร์ GCC/G++/GFortran มาให้แล้ว)
- ดาวน์โหลด AIfES_for_Arduino จาก GitHub แล้วแตกไฟล์ซิปออกมา
- ดาวน์โหลดไฟล์ main.c จากโปรเจกต์นี้
- ย้ายไฟล์ main.c ไปไว้ในโฟลเดอร์:
AIfES_for_Arduino\\src
สร้างโปรเจกต์ใหม่ใน Code::Blocks:
- สร้างโปรเจกต์ใหม่:
File->new->Project... - เลือก "
Console application" - เลือกภาษาเป็น "
C" - ตั้งชื่อโปรเจกต์สักชื่อ เราใช้ชื่อ "AIfES_XOR_training"
- คอมไพเลอร์: เลือก
GNU GCC Compiler - กดสร้างโปรเจกต์ได้เลย!
ติดตั้ง AIfES ใน Code::Blocks:
- ลบไฟล์ main.c ที่โปรแกรมสร้างให้อัตโนมัติออกจากโปรเจกต์:
คลิกขวาที่ไฟล์ main.c -> เลือกremove file from project
Project -> Add files recursively...AIfES_for_Arduino\\src (ไฟล์ main.c ที่ดาวน์โหลดมาก็ควรจะอยู่ในนั้นแหละ)
- ไปที่:
Project->Build options->Search directories->Compiler - กดปุ่ม
Addแล้วไปที่โฟลเดอร์AIfES_for_Arduino\\srcอีกที - ตอบคำถาม Keep this as a relative path? ด้วย
yes - เซฟโปรเจค
- เป็นอันว่า AIfES ติดตั้งเรียบร้อยแล้วในโปรเจคของน้อง
Code::Blocks มันจะแยกไฟล์เฮดเดอร์กับซอร์สโค้ดให้เองอัตโนมัติ
ขั้นตอนเทรนโมเดลใน Code::Blocks
สำหรับการเทรนนี้ ค่า weight จะถูกสุ่มขึ้นมาในช่วง -2 ถึง 2
เราใช้ ADAM optimizer ในการเทรน แบบ full batch จำนวน 100 epochs
ขั้นตอนต่อไปคือเริ่มเทรน:
- Build โปรเจค
- Run โปรแกรม
ถ้าเจอปัญหา (Troubleshooting):
ขึ้นอยู่กับการตั้งค่า Code::Blocks ของน้อง บางทีไฟล์สองไฟล์นี้อาจคอมไพล์ไม่ผ่าน:
- ailayer_dense_cmsis.c
- aimath_f32_cmsis.c
ในไฟล์พวกนี้จะมีบรรทัด include แบบนี้: #include "../../../aifes.h"
ให้น้องเปลี่ยนในทั้งสองไฟล์เป็น: #include "aifes.h"
เพราะว่าเรา import AIfES ด้วย relative path มันอาจจะงงๆ หน่อย หลังจากเปลี่ยนแล้วโปรเจคควรจะคอมไพล์ผ่าน

หลังเทรนเสร็จ ต้องมาตรวจสอบผลการเรียน(รู้นะว่าอยากโดด) ดูจากค่า loss และเปรียบเทียบผลลัพธ์ที่ได้กับที่คาดหวัง (ดูในกรอบสีแดง)

แน่นอนว่าเราไม่การันตีผลการเทรน 100% เพราะ weight มันสุ่มมา เรามีคำเตือนโผล่ขึ้นมาให้ถ้า loss สูงกว่า 0.3 นะ

ท้ายสุดของผลลัพธ์ จะมีค่า weight ที่เทรนเสร็จแล้ว พร้อมจัดรูปแบบเป็น C array ให้เลย นำค่านี้ไปใส่ใน Arduino Sketch ได้ทันที

ขั้นตอน Inference บน Arduino Board
ขั้นตอนสุดท้ายแล้วน้อง ไปรันโมเดลบนบอร์ด Arduino กัน เปิดสเก็ตตัวอย่างที่เข้ากันได้จาก AIfES examples:
File -> Examples -> AIfES for Arduino -> 0_Universal -> 0_XOR -> 4_XOR_Inference_keras
ก็อปปี้ค่า weight ที่เราเทรนได้ ไปวางในตำแหน่งที่เตรียมไว้ให้ มีสองที่นะ หนึ่งสำหรับ hidden layer อีกที่สำหรับ output layer เขียนทับค่า weight จากตัวอย่างเดิมไปเลย

- อัพโหลดสเก็ตช์ลงบอร์ดของน้องไปเลย
- เปิด
Serial Monitor(115200 baud) ขึ้นมา - พิมพ์คำว่า "inference" แล้วกด
return
สเก็ตช์จะป้อนข้อมูล 0 กับ 1 เข้าไปใน ANN ที่เราฝึกไว้ ตามตารางด้านล่างนี้ ผลลัพธ์ที่ได้ควรจะใกล้เคียง 1 มากที่สุด อย่าให้มันหลุดไปไหนล่ะ

ลองเอาเลขที่ได้จาก Serial Monitor ไปเทียบกับผลลัพธ์ตอนฝึกในคอมดู ว่ามันตรงกันรึเปล่า

Edge-AI Model Training Framework
โปรเจคนี้เป็นคู่มือแบบจัดเต็ม ตั้งแต่ฝึก Neural Network ตัวจิ๋วบน PC ไปจนถึงเอามาใส่ลง Arduino ด้วยไลบรารี AIfES (Artificial Intelligence for Embedded Systems) ตัวนี้แหละ
- ฝึกฝนบน PC: ใช้ Code::Blocks IDE รันเคอร์เนลฝึก AIfES บนคอมปกติ ฝึกเสร็จไวปร๋อ เพราะไม่ต้องมานั่งรอฝึกบนไมโครคอนโทรลเลอร์ที่ช้ากว่า
- ส่งต่อน้ำหนัก: พอโมเดลฝึกจนได้ที่บน PC แล้ว เคอร์เนล AIfES จะพ่นไฟล์ C-header ออกมา ซึ่งข้างในมีน้ำหนัก (weights) ที่ฝึกเสร็จแล้วอยู่ น้องก็แค่คัดลอกไฟล์นี้ไปวางใน Arduino sketch ของน้องได้เลย ง่ายๆ