บทเรียน 5.8 — quantize และ Vela: เอาโมเดลของเราขึ้น Ethos-U55

เอาโมเดลของเราขึ้น Ethos-U55 ด้วย Vela แล้วเทียบสามเป้าหมาย

โมดูล 5 — ฝึกโมเดลและนำไปใช้หลายเป้าหมาย

บล็อก Training (บทเรียน 5.3–5.5 → บทเรียน 5.6–5.7 → บทเรียน 5.8–5.9) · ปิดท้ายวงจร Pillar 4

คาถาประจำบทเรียน: "โมเดล int8 ไฟล์เดียว — เว็บกับ Cortex-A ใช้ตรงๆ ได้ แต่ NPU ขอขั้นเดียว: Vela คอมไพล์ก่อน แล้วมันจะเร็วและประหยัดที่สุด"

quantize → TFLite → Vela → รันบนบอร์ดผ่าน edge_ai · Python → MPY

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

เปิดบทเรียนด้วยของจริงก่อน

เหมือนทุกบทเรียน เราเริ่มแบบ กลับด้าน — เอาปลายทางที่น่าตื่นเต้นมาให้เห็นก่อน แล้วค่อยแกะว่าไปถึงตรงนั้นได้ยังไง วันนี้ปลายทางคือ โมเดลที่เราเทรนเอง (บทเรียน 5.3–5.5) กำลังรันบน NPU จริง แล้วโผล่ใน edge_ai.models() เคียงข้างโมเดลโรงงาน

โมเดลเราบน NPU รันจริง เห็นก่อน Vela ทำอะไร int8 → ethos-u op เติม/วัดเอง bench 3 เป้าหมาย เลือกที่อยู่ งานจริง

บทเรียน 5.3–5.5 เราเทรนได้ .tflite, บทเรียน 5.6–5.7 พิสูจน์ว่ามันรันบนเว็บได้ตรงกับ PC. เหลือเป้าหมายสุดท้ายที่ยากที่สุดแต่คุ้มที่สุด — ชิปเล็กๆ ตรงหน้า วันนี้เราพามันไปถึง

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

เป้าหมายของชุดบทเรียนนี้

จบชุดบทเรียนนี้เราจะเดินครบ แล้วปิดท้ายด้วยโมเดลของเราเองบน NPU:

  1. ทำไม MCU ต้องมีขั้นพิเศษ ที่เว็บกับ Cortex-A ไม่ต้องมี (Vela / custom op)
  2. int8 PTQ + Vela — จาก .tflite int8 → _vela.tflite ที่ NPU อ่านออก ด้วย quantize_vela.sh
  3. สัญญา AIM_* — สี่ฟังก์ชันที่ห่อโมเดลให้ edge_ai เรียกได้ (ai_models/README.md ของ SDK)
  4. เทียบสามเป้าหมาย — วัด accuracy/latency จริงของ MCU vs Web vs PC แล้วอ่านตาราง
  5. ลงมือ: bench int8 บน PC → รัน Vela → wrap → flash → อ่าน edge_ai.latency() บนบอร์ด

ปลายทางของวันนี้: โมเดล gesture ของเราโผล่ใน edge_ai.models() ให้ verdict บน NPU แล้วเราเติมช่อง MCU ในตารางเทียบเป้าหมายได้ด้วยเลขจริง

วันนี้เน้น "quantize ให้ถูก + เทียบให้เป็น" — ไม่ใช่แค่ทำให้รันได้ แต่ต้อง วัดได้ ว่าแต่ละที่แลกอะไรกับอะไร

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

ชุดบทเรียนนี้อยู่ตรงไหนของวงจร

เราอยู่ปลายบล็อก Training (Pillar 4) — ต่อยอดตรงจาก บทเรียน 5.3–5.5 กับ 5.6–5.7 มาปิดวง "train once, run everywhere" ให้ครบทั้งสามเป้าหมาย

5.3–5.5 · เทรน Keras → model_int8 .tflite (int8) 5.6–5.7 · Web parity PC ↔ เบราว์เซอร์ ไฟล์เดิม float I/O 5.8–5.9 · MCU (วันนี้) Vela → NPU + เทียบ _vela.tflite (MCU-only) 6.1–6.2+ Apps เอาไปทำแอป โมเดล .tflite ไฟล์เดียว เดินครบสามเป้าหมาย

บทเรียน 5.6–5.7 เราจับ "ไฟล์เดียว รันหลายที่" ได้แล้ว วันนี้เติมเป้าหมายที่มี ข้อยกเว้น ข้อเดียว — NPU ต้องคอมไพล์เพิ่ม เพราะมันไม่ใช่ CPU ที่รันกราฟทั่วไปได้

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

ปมของวันนี้ — ทำไม MCU ไม่เหมือนใคร

จำตาราง "train once, run everywhere" จาก บทเรียน 1.1–1.3 ได้ไหม มีบรรทัดเดียวที่ column "ทำอะไรกับไฟล์" ไม่ว่าง:

เป้าหมาย ทำอะไรกับ .tflite int8 รันด้วย
Web ใช้ไฟล์เดิม (แปลงเป็น float I/O) LiteRT.js
Cortex-A (Linux) ใช้ไฟล์เดิม ไม่แก้ ai-edge-litert
PC / Docker ใช้ไฟล์เดิม ai-edge-litert
MCU + Ethos-U55 คอมไพล์ผ่าน Vela เพิ่ม 1 ครั้ง TFLite-Micro บนบอร์ด
  • Web/Cortex-A/PC ล้วนเป็น CPU (หรือ GPU/WASM) ที่รันกราฟ TFLite ทั่วไปได้ตรงๆ
  • NPU ไม่ใช่ CPU — มันเป็นวงจรเฉพาะทางสำหรับคูณเมทริกซ์ ต้องมีคน "แปล" กราฟให้มันก่อน คนนั้นคือ Vela

นี่ไม่ใช่ข้อเสียของ MCU มันคือราคาของความเร็ว: NPU เร็วและประหยัดกว่ามาก แลกกับต้องคอมไพล์เพิ่มหนึ่งขั้น เราจ่ายขั้นนั้นวันนี้

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

int8 quantization — ทวนจาก บทเรียน 5.3–5.5

โมเดล MCU ต้องเป็น full-integer int8 — น้ำหนักและ activation ทุกตัวเป็นจำนวนเต็ม 8 บิต ไม่ใช่ float 32 บิต

float32 (ตอนเทรน) แม่นสุด · ใหญ่ · กินไฟ int8 (บนชิป) เล็กลง ~4 เท่า · NPU รันได้ PTQ + representative dataset
  • PTQ (Post-Training Quantization) ใช้ "representative dataset" หา scale/zero ที่พอดีกับช่วงค่าจริง
  • ทุก tensor เก็บคู่ (scale, zero) ไว้ — เวลาใช้งานเราต้อง quantize input ด้วยคู่นี้เป๊ะ (q = round(x/scale + zero))
  • accuracy ลดลงเล็กน้อยจาก float แต่แลกกับ ขนาดเล็กลง 4 เท่า และ NPU รันได้ — คุ้มมากบนชิปเล็ก

model_int8.tflite จาก บทเรียน 5.3–5.5 คือจุดตั้งต้นของวันนี้ — เราไม่เทรนใหม่ เราแค่พาไฟล์นี้ไปให้ NPU รัน

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

ภาพเคลื่อนไหว — Quantization: float32 → int8

ภาพเคลื่อนไหว: ค่า float32 ที่ต่อเนื่องถูกปัดไปยังขั้นของ int8 ที่ใกล้ที่สุด พร้อมสูตร scale และ zero_point

▸ ลองเล่นสด (GeoGebra): เปิด Interactive Math Lab — ลากจุด/เลื่อนสไลเดอร์ดูสมการขยับตาม

ค่าต่อเนื่อง "snap" ไปยังกริด int8 ที่ใกล้ที่สุด — โมเดลเล็กลง ~4 เท่า และเร็วขึ้นบน NPU

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

คณิตของ int8 — quantize / dequantize

หัวใจของ int8 คือสูตรสั้นๆ สองบรรทัด แปลง float ↔ จำนวนเต็ม 8 บิต ไปกลับ ด้วยคู่ค่าที่โมเดลฝังไว้เอง

quantize (float → int8, ตอนป้อน input เข้าโมเดล):

q=round⁡ ⁣(xs)+zq = \operatorname{round}\!\left(\frac{x}{s}\right) + z

dequantize (int8 → float, ตอนอ่าน output กลับมา):

x=(q−z)⋅sx = (q - z)\cdot s

อ่านสัญลักษณ์แบบภาษาคน:

  • xx = ค่าจริงแบบ float (เช่น ค่าจากเซนเซอร์ที่ normalize แล้ว)
  • qq = ค่าจำนวนเต็ม 8 บิตที่เก็บบนชิป อยู่ในช่วง [−128,127][-128, 127]
  • ss (scale) = "หนึ่งขั้นของ int8 เท่ากับกี่หน่วยของ float" — ตัวคูณระยะ
  • zz (zero-point) = ค่า qq ที่แทน x=0x = 0 พอดี — เลื่อนจุดศูนย์ให้ตรง
  • round⁡\operatorname{round} + การ clip เข้ากรอบ [−128,127][-128,127] คือที่มาของ quantization error เล็กน้อย

ทำไมเรื่องนี้สำคัญกับชุดบทเรียนนี้: PTQ (บทเรียน 5.3–5.5) เป็นคนหา s,zs, z ที่พอดีกับช่วงค่าจริงจาก representative dataset แล้ว ฝังคู่ (s,z)(s,z) ไว้ในทุก tensor เราจึงอ่านมาใช้ตรงๆ ไม่ต้องเดา (ดูโค้ด in_scale, in_zero = inp["quantization"] ในสไลด์ถัดๆ ไป) และเพราะ Vela ไม่แตะสูตรนี้เลย accuracy บน NPU จึงควรเท่ากับ int8 บน PC (ต่างได้แค่ระดับการปัดเศษของ kernel) — ถ้าบนบอร์ดเพี้ยนมาก แปลว่า front-end ใช้ s,zs,z ไม่ตรง ไม่ใช่ Vela ผิด

จำง่ายๆ: ss คือ "ขนาดหนึ่งก้าว" ของ int8 · zz คือ "ศูนย์อยู่ตรงไหน" — สองค่านี้เป๊ะเมื่อไร float กับ int8 ก็เล่าเรื่องเดียวกัน

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

Vela คืออะไร กันแน่

ethos-u-vela คือ คอมไพเลอร์ของ Arm สำหรับ Ethos-U NPU มันรับ .tflite int8 แล้วมองหา subgraph ที่ NPU ทำได้ เอาไปแทนด้วย custom op ตัวเดียวชื่อ ethos-u

model_int8.tflite Conv · Dense · ReLU (op มาตรฐาน TFLite) CPU รันได้ · NPU ยังไม่รู้จัก Vela ethos-u55-128 model_int8_vela.tflite [ ethos-u custom op ] + เศษที่ NPU ทำไม่ได้ → CPU MCU-only · เบราว์เซอร์รันไม่ได้
  • --accelerator-config ethos-u55-128 = บอก Vela ว่า NPU ตัวเราคือ U55 ที่ 128 MAC/รอบ
  • op ที่ NPU ทำไม่ได้ Vela ปล่อยให้ CPU (M55) ทำ — ผลลัพธ์คือ "กราฟผสม" ที่ TFLite-Micro บนบอร์ดรันได้

จุดสำคัญ: Vela ไม่แก้คณิตของโมเดล มันแค่จัดของใหม่ให้ NPU เร่งได้ → accuracy ควรเท่าเดิม (ต่างได้แค่ระดับการปัดเศษ) สิ่งที่เปลี่ยนคือ latency กับพลังงาน นี่คือเหตุผลที่ int8 บน PC = ground truth ของ MCU

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

quantize_vela.sh — คำสั่งเดียวจบ

สคริปต์ในชุดบทเรียนนี้ห่อ Vela ไว้ให้เหลือคำสั่งเดียว รับ .tflite int8 คืน _vela.tflite ใน output/:

./quantize_vela.sh model_int8.tflite
#  -> ./output/model_int8_vela.tflite

ข้างในสคริปต์ทำแค่นี้ (อ่านได้เต็มใน quantize_vela.sh):

set -euo pipefail
MODEL="${1:-model_int8.tflite}"
[ -f "$MODEL" ] || { echo "no such file: $MODEL"; exit 1; }
vela --accelerator-config ethos-u55-128 --optimise Performance "$MODEL"
  • --optimise Performance = ให้ Vela เน้นความเร็ว (มีอีกโหมด Size เน้นประหยัดหน่วยความจำ)
  • vela ติดตั้งอยู่ใน Docker image ของ บทเรียน 5.3–5.5 แล้ว — ไม่ต้องลงเอง รันในคอนเทนเนอร์เดิมได้เลย

set -euo pipefail คือนิสัยสคริปต์ที่ดี: ถ้าขั้นไหนพลาด สคริปต์หยุดทันที ไม่เดินต่อแบบเงียบๆ ให้เราหลงคิดว่าสำเร็จ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

สามไฟล์ .tflite — ไฟล์ไหนไปเป้าหมายไหน

พอถึงตรงนี้เรามีไฟล์ .tflite สามหน้าตา จากน้ำหนักชุดเดียวกัน อย่าสับสน — แต่ละไฟล์มีบ้านของมัน

model.keras float · แหล่งความจริง model_int8.tflite int8 in/out → PC · Cortex-A · Vela model_int8_vela.tflite ethos-u op → MCU + NPU เท่านั้น model_web.tflite float I/O → เบราว์เซอร์ (LiteRT.js) PTQ (5.3–5.5) convert_web (5.6–5.7)
  • model_int8.tflite เป็นตัวกลาง: ใช้เองบน PC/Cortex-A ได้ และ เป็น input ของ Vela ไปต่อเป็นไฟล์ MCU
  • _vela.tflite มี ethos-u custom op → เบราว์เซอร์/Cortex-A รันไม่ได้ · model_web.tflite float I/O → NPU ไม่ใช้

จำง่ายๆ: หนึ่งน้ำหนัก สามบรรจุภัณฑ์ — เลือกบรรจุภัณฑ์ให้ตรงเป้าหมาย ถ้าเอาไฟล์ผิดไปผิดที่ มันจะโหลดไม่ขึ้นเลย (fail ชัด ไม่ใช่ fail เงียบ)

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

ได้ไฟล์ Vela แล้ว ยังรันบนบอร์ดไม่ได้ทันที

_vela.tflite เป็นแค่ "ไบต์ของกราฟ" บอร์ดยังไม่รู้จักมันในฐานะโมเดล เราต้อง ห่อ ด้วยสัญญา 4 ฟังก์ชันที่ edge_ai เรียกเป็น — เรียกว่า สัญญา AIM_* (ai_models/README.md ของ SDK)

int  AIM_GESTURE_init(void);                 // 0 = ok, <0 = fail
int  AIM_GESTURE_enqueue(const float *in);   // ป้อน input หนึ่ง window
int  AIM_GESTURE_dequeue(float *out);        // 0 = มี verdict (เติม out[]), <0 = ยังไม่มี
void AIM_GESTURE_finalize(void);             // (ไม่ถูกเรียกตอน runtime)
  • นี่คือ "รูปร่าง" เดียวกับที่โมเดลโรงงานทั้ง 6 ตัวใช้ — edge_ai ไม่สนว่าข้างในเป็นโมเดลอะไร ขอแค่มี 4 ฟังก์ชันนี้
  • return codes มีชุดตายตัว: SUCCESS(0), NODATA(-1), ERROR(-2), STREAMEND(-3)

ทะเบียนโมเดลของ edge_ai เป็น shape-driven — พอโมเดลเรามีสัญญาครบ มันจะโผล่ใน edge_ai.models() เองโดยไม่ต้องแตะ MicroPython หรือ IPC เลยแม้แต่บรรทัดเดียว

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

สองทางในการ wrap โมเดลของเรา

_vela.tflite → สัญญา AIM_* ทำได้สองทาง (ai_models/README.md ของ SDK):

Path A — DEEPCRAFT Converter ป้อน .tflite/.keras เข้าตัวแปลง มันสร้าง model_gesture.c/.h ให้เอง รวม DSP front-end (FFT/mel/window) ให้ด้วย คอร์สปกติใช้ทางนี้ (ราบรื่นสุด) กราฟดิบไม่มี front-end — ตัวแปลงเติมให้ Path B — hand-wrap TFLite-Micro xxd -i ฝังไบต์ _vela.tflite เป็น C array ตั้ง MicroInterpreter + AddEthosU() เขียน front-end เอง (ต้องตรงกับตอนเทรน) คุมได้เต็ม — สาย researcher (7.3–7.4) ยากกว่า แต่ไม่พึ่งเครื่องมือภายนอก

กับดักที่แท้จริงไม่ใช่ตัวกราฟ แต่คือ feature parity — โมเดลเสียง/เรดาร์คาดหวัง feature vector เฉพาะ (เช่น 512-pt Hann FFT → 20-band mel → log) ต้องทำ front-end ให้เป๊ะเหมือนตอนเทรน มิสแมตช์ = ล้มเหลวแบบเงียบๆ อันดับ 1

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

3 edits ที่ทำให้โมเดลโผล่บนบอร์ด

เมื่อ wrap เสร็จ การ register โมเดลใหม่ใช้แก้แค่ 3 จุด (ai_models/README.md ของ SDK):

1 · Makefile เพิ่ม gesture ใน AI_MODELS auto-derive define/mem/guard 2 · ai_engine.c GESTURE_ROW + s_models[] ชี้ไป AIM_GESTURE_* 3 · วางไฟล์โมเดล model_gesture.c/.h หรือ .a ลงใน ai_models/
  • แล้ว rm -rf proj_cm55/build; make program EDGE_AI_MODEL=combo + hard power-cycle — เท่านั้น
  • ไม่ต้องแก้ MicroPython, ไม่ต้องแก้ IPC — เพราะทะเบียนกับ model-link เป็น shape-driven

เฟิร์มแวร์มี FALL_ROW, GESTURE_ROW, KEYWORD_ROW คอมเมนต์ค้างไว้เป็นตัวอย่าง pattern นี้อยู่แล้ว — โมเดลที่ใช้เซนเซอร์เดิม (IMU) ไม่ต้องเขียน feed ใหม่

หมายเหตุ: ซอร์สเฟิร์มแวร์ BENTO ที่ใช้ทำคอร์สนี้ยังไม่เปิด ใน SDK สาธารณะ tesaiot-pse84-devkit-sdk ai_engine มาเป็นไลบรารี prebuilt จึงเพิ่มโมเดลใหม่ด้วย ai_engine_register() จากโค้ดของเราตอนรัน หรือใส่โมเดลแทนช่องเดิม ตามหัวข้อ Filling a model slot ใน proj_cm55/modules/ai_models/README.md

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

หัวใจของชุดบทเรียน — เทียบสามเป้าหมาย

พอโมเดลรันได้ทุกที่แล้ว คำถามวิศวกรที่แท้จริงคือ "มันควรอยู่ที่ไหน?" — คำตอบมาจากการวัด ไม่ใช่ความรู้สึก

เร็ว · ประหยัดไฟ · เล็ก แรง · ยืดหยุ่น · กินไฟ MCU + NPU _vela.tflite latency ต่ำสุด power ต่ำสุด Web model_web.tflite float I/O แล้วแต่เครื่องผู้ใช้ PC / Cortex-A model_int8.tflite latency กลาง ตั้งต้น/ground truth

accuracy ของทั้งสามควร ตรงกัน (int8 กราฟเดียวกัน) แต่ latency กับพลังงานต่างกันคนละโลก — สคริปต์วันนี้วัดตัวเลขจริงมาวางเทียบให้เห็นด้วยตา

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

วัด latency แต่ละเป้าหมายยังไงให้ยุติธรรม

เราวัด "เวลาอนุมานล้วน" (เฉพาะช่วง invoke) ไม่รวม normalize/quantize — เพราะ edge_ai.latency() บนบอร์ดก็วัดเฉพาะช่วงนั้น จะได้เทียบตรงประเด็น

เป้าหมาย วัดด้วย ได้เลขจาก
PC / Cortex-A time.perf_counter() คร่อม it.invoke() สคริปต์ s14 บน PC
Web performance.now() คร่อม model.run() เบราว์เซอร์ (หรือ bench float ใน s14)
MCU + NPU r['latency_ms'] จาก edge_ai.result() รันบนบอร์ดจริง
t0 = time.perf_counter()
it.invoke()                              # อนุมานล้วน ไม่รวม pre/post
total_ms += (time.perf_counter() - t0) * 1000.0

ตัวเลข MCU ต้องมาจากบอร์ดจริงเท่านั้น — เราวัดบน PC ไม่ได้ เพราะไม่มี NPU. สคริปต์จึงเว้นช่อง MCU ไว้ให้เราเอา edge_ai.latency() มาเติมด้วย --mcu-ms

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

accuracy ต้องตรง — นี่คือ parity อีกชั้น

บทเรียน 5.6–5.7 เราพิสูจน์ parity ระหว่าง PC กับเว็บมาแล้ว วันนี้ขยายไป NPU: int8 บน PC = accuracy ที่ NPU ควรได้ เพราะ Vela ไม่แตะคณิต (ต่างได้แค่ระดับการปัดเศษของ kernel)

# bench int8 บน PC — ได้ทั้ง accuracy (ground truth) และ latency
correct += int(o.argmax() == y[i])       # นับคลาสที่ชนะตรงกับคลาสจริง
acc = correct / len(X)
  • ถ้าบนบอร์ด accuracy ไม่ตรง กับ PC — ปัญหาไม่ได้อยู่ที่ Vela แต่อยู่ที่ front-end (normalize/quantize/feature) ที่ feed บนบอร์ดทำไม่เหมือนตอนเทรน
  • Web อาจต่างเล็กน้อยเพราะ activation เป็น float (int8 ถูกบีบมากกว่า) — เห็นได้ในตารางว่า "ใกล้ แต่ไม่เป๊ะ 100%"

บทเรียนซ้ำจาก บทเรียน 5.6–5.7 ที่ยกระดับ: feature parity คือกับดัก ไม่ใช่ตัวกราฟ — ทั้งสามเป้าหมายต้องเดิน front-end เดียวกัน accuracy ถึงจะตรง

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

ทำไม NPU ถึงเร็วและประหยัดกว่า

accuracy เท่ากันแล้ว จุดที่ NPU ชนะขาดคือ latency กับ พลังงานต่อการอนุมาน — และสองอย่างนี้มาจากเหตุผลเดียวกัน

CPU (M55) ทำเมทริกซ์ คูณ-บวกทีละชุด ผ่านคำสั่งทั่วไป ยืดหยุ่นทำอะไรก็ได้ แต่ไม่เฉพาะทาง งานเมทริกซ์ใหญ่ = หลายรอบสัญญาณนาฬิกา latency สูงกว่า · กินไฟต่ออนุมานมากกว่า NPU (Ethos-U55) ทำเมทริกซ์ วงจร MAC ขนาน 128 ตัว/รอบ ออกแบบมาทำ int8 conv/dense โดยเฉพาะ งานเดียวกันเสร็จในรอบน้อยกว่ามาก latency ต่ำ · พลังงานต่อผลลัพธ์ต่ำสุด
  • NPU ไม่ได้ "ฉลาดกว่า" CPU — มันแค่ทำ งานเดียว (คูณเมทริกซ์ int8) ได้ขนานและประหยัด ที่ CPU ทำทีละนิด
  • พลังงานต่ำเป็นผลพลอยได้ของความเร็ว: เสร็จเร็ว = ปลุกวงจรสั้น = บอร์ดกลับไปหลับ (แบตอยู่ได้นาน)

นี่คือเหตุผลที่ Vela คุ้มค่าจ่ายขั้นคอมไพล์เพิ่ม — เราแลก "หนึ่งขั้นตอนตอน build" กับ "เร็วขึ้นหลายเท่า + แบตอยู่นานขึ้นมาก ตอน run ทุกครั้ง"

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

อ่านตารางให้ลึก — accuracy เท่ากันไม่ได้แปลว่าจบ

ตารางเทียบให้ตัวเลข แต่การอ่านมันคือทักษะวิศวกร ระวังสามกับดักนี้:

  • accuracy รวมหลอกได้ — 90% ฟังดูดี แต่ถ้าคลาส shaking พลาดครึ่งหนึ่งล่ะ? ดู confusion matrix (จาก eval_pc.py) ไม่ใช่แค่เลขรวม นี่คือบทเรียน false positive/negative จากบล็อก Analysis ที่ออกดอกตรงนี้
  • latency เฉลี่ยซ่อน worst-case — งาน real-time สนใจ "ช้าสุดกี่ ms" ไม่ใช่แค่เฉลี่ย บนบอร์ดให้เก็บ edge_ai.latency() หลาย ๆ ครั้งแล้วดูค่าสูงสุดเอง (ฝั่ง C มี inference_us_max ใน ai_result_t)
  • Web ต่างเล็กน้อยเป็นเรื่องปกติ — activation float ไม่ถูกบีบเท่า int8 ถ้าต่างเกิน tolerance (เช่น 0.02) ค่อยสงสัย front-end
# เทียบให้ครบ: ไม่ใช่แค่ accuracy รวม แต่ดูว่าพลาดคลาสไหน (eval_pc.py)
for i, row in enumerate(cm):            # cm = confusion matrix
    print("%-8s %s" % (dt.CLASSES[i], row))

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

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0