หกโมเดลกับ edge_ai API: แอปที่โฟกัสโมเดลเดียว
โมดูล 6 — แอป Edge AI · สไลด์: slides.md · ภาพรวมโมดูล · หน้าหลักสูตร
เปิดโมดูลแอป จากเมนูที่ให้เลือกทุกโมเดลไปสู่แอปที่โฟกัสโมเดลเดียว เล็งโมเดลด้วย find_model() แทนเลข index อ่าน scores ทุกคลาสกับ latency_ms ให้เป็น และต่อ verdict เข้ากับ action แรกคือการนับเมื่อคลาสเป้าหมายมั่นใจถึง CONF_FLOOR เฉพาะจังหวะขอบขาขึ้น
เป้าหมาย
หัวข้อที่มีชื่อว่า “เป้าหมาย”เมื่อจบบทเรียนนี้ คุณจะ:
- เปรียบเทียบแอปเมนูกับแอปโฟกัสโมเดลเดียว และบอกได้ว่างานแบบใดควรใช้แบบใด
- อธิบาย find_model() ที่ถอยสามชั้น (ชื่อ → เซนเซอร์ → ตัวแรก) และเหตุผลที่ไม่ควร hard-code เลข index ของโมเดล
- อ่าน dict ของ edge_ai.result() ได้ครบ ทั้ง top ที่มาจาก argmax, conf ที่เป็นคะแนนสูงสุด, scores ทุกคลาส, latency_ms และ seq ที่ใช้วาดจอเฉพาะผลใหม่
- เขียนเงื่อนไขนับ label == TARGET_CLASS และ conf ≥ CONF_FLOOR (0.50) ที่นับเฉพาะขอบขาขึ้น และอธิบายขีดจำกัดของโมเดล Ready-Model แบบประเมินผล
ก่อนเริ่ม
หัวข้อที่มีชื่อว่า “ก่อนเริ่ม”ผ่านโมดูล 1 มาแล้ว เคยใช้ edge_ai.models(), select(), result() และ stop() และจำโครง verdict สู่ action จากบทเรียน 1.6 ได้
เปิดตัวอย่าง 16_edge_ai_sound_events.py ไว้ใน BENTO IDE
- อุปกรณ์: บอร์ด TESAIoT Dev Kit ที่ลงเฟิร์มแวร์ MicroPython ของ BENTO แล้ว หรือ BENTO Emulator ใน BENTO IDE — บน Emulator คะแนนของโมเดลเป็นค่าจำลอง โมเดลเสียงขยับตามลูกบิด POTEN แต่คลาสเหตุการณ์ยังไม่ชนะ unlabelled และไม่มีโมเดล Push เสียงจริงกับเรดาร์ต้องใช้บอร์ด
- เรียนมาก่อน: บทเรียน 5.9 — ลงมือทำ: เทียบสามเป้าหมาย MCU, Web และ PC
ดูของจริงก่อน
หัวข้อที่มีชื่อว่า “ดูของจริงก่อน”รัน 16_edge_ai_sound_events.py บนบอร์ดแล้วสลับ Cough, Alarm และ Siren ใน dropdown เดียว ดูแถบสองคลาสขยับเมื่อมีเสียง
ถามตัวเองว่า ถ้าเครื่องนี้ต้องนับเสียงไอในห้องผู้ป่วยทั้งคืน ผู้ใช้ควรต้องเลือกโมเดลเองหรือไม่
เมนูเลือกโมเดลเหมาะกับการสำรวจและเดโม แต่สินค้าจริงแทบทั้งหมดเป็น แอปโฟกัส: เล็งโมเดลเดียวตอนเปิดแอป UI ออกแบบเฉพาะงาน และต่อ verdict เข้ากับ action
ตัวอย่าง 13 ถึง 16 มีก้อนเดียวกัน คือ find_model() → select() → ลูป result() → วาด verdict กับแถบ → finally: stop() บนบอร์ดมีหกโมเดล
(Motion, Baby Cry, Push, Cough, Alarm, Siren) ส่วน Emulator มีห้า ลำดับจึงไม่เท่ากัน find_model() หาจากคีย์เวิร์ดในชื่อก่อน ไม่เจอค่อยใช้โมเดลแรกที่ตรง
sensor (เช่น edge_ai.SENSOR_MIC = 2) และสุดท้ายใช้ตัวแรกกันแอปล่ม select(3) ตายตัวจะพังทันทีที่ทะเบียนเปลี่ยน
dict ของ result() ให้มากกว่าคลาสที่ชนะ: top คือ $\hat{y} = \arg\max_i s_i$ conf คือ $s_{\hat{y}}$ scores ใช้วาดแถบทุกคลาสให้เห็นว่าโมเดลลังเลหรือชัวร์
latency_ms บอกเวลาอนุมานบน NPU ซึ่งต่างกันตามโมเดล และ seq ใช้วาดจอเฉพาะเมื่อมีผลใหม่ argmax เลือกผู้ชนะเสมอแม้ 0.51 ต่อ 0.49
เราจึงตั้งประตูของ action: นับเมื่อ r['label'] == TARGET_CLASS and r['conf'] >= edge_ai.CONF_FLOOR (0.50) และนับเฉพาะ ขอบขาขึ้น (is_target and not was_target)
เพราะไอหนึ่งครั้งกินหลายผลอนุมาน ตั้งเกณฑ์สูงได้ความชัวร์แต่พลาดเสียงเบา ตั้งต่ำจับไวแต่ false positive มาก
Cough, Alarm และ Siren เป็น DEEPCRAFT Ready-Model ของ Imagimob AB (บริษัทในเครือ Infineon) แบบประเมินผล ใช้ได้เพื่อการทดลองเท่านั้น
และจำกัดจำนวนครั้งอนุมาน ถ้าผลค้างนิ่งและ seq ไม่ขยับ นั่นคือเพดานของโมเดล ไม่ใช่โค้ดพัง ผู้เขียนแนะนำให้รีบูตบอร์ด
เมื่อฝึกโมเดลเองได้แบบโมดูล 5 ข้อจำกัดนี้ก็หายไป
ตัวอย่างสมบูรณ์
หัวข้อที่มีชื่อว่า “ตัวอย่างสมบูรณ์”14_edge_ai_babycry.py การ์ดผลลัพธ์กับแถบความมั่นใจของโมเดลไมค์ 15_edge_ai_radar_push.py โมเดลเรดาร์ Push (ยืนห่างราว 60 ซม. ต้องใช้บอร์ดที่มีเรดาร์)
16_edge_ai_sound_events.py เมนูย่อยสามโมเดลเสียง 17_latency_min_max_avg.py เก็บ latency 20 รอบแล้วสรุปต่ำสุด สูงสุด เฉลี่ย
และ 18_switch_cost.py จับเวลาการสลับโมเดลด้วย select() ให้เห็นว่าการสลับถี่ ๆ มีราคา (สองไฟล์หลังย้ายมาจากคอร์ส AIoT ของผู้เขียน)
| ไฟล์ | ไฟล์นี้สอน |
|---|---|
| examples/14_edge_ai_babycry.py | Edge AI: Baby Cry (ไมโครโฟน) — ตรวจเสียงเด็กร้องบนบอร์ด (ไม่ต้องต่อเน็ต) |
| examples/15_edge_ai_radar_push.py | Edge AI: Radar Push (เรดาร์ 60 GHz) — จำแนกท่าทางมือด้วยเรดาร์บนบอร์ด |
| examples/16_edge_ai_sound_events.py | Edge AI: Sound Events (Cough / Alarm / Siren) — 3 โมเดลไมค์ ใน dropdown เดียว |
| examples/17_latency_min_max_avg.py | วัดว่าโมเดลใช้เวลาคิดนานแค่ไหน |
| examples/18_switch_cost.py | สลับโมเดลระหว่างที่โปรแกรมกำลังรัน |
สไลด์ของบทเรียนนี้อ้างถึงไฟล์ที่อยู่ในบทเรียนอื่นหรือใน shared/ ด้วย:
- m01-onboarding/l06-edge-ai-app-anatomy/examples/13_edge_ai_motion.py — Edge AI: Motion (IMU) ด้วย API ใหม่ edge_ai — เห็นคะแนนทุกคลาส + latency
- m06-apps/l02-focused-app-lab/practice/s15_apps.py — แอป Edge AI แบบ “โฟกัสโมเดลเดียว” (ฉบับฝึกเติมโค้ด)
เช็กความเข้าใจ
หัวข้อที่มีชื่อว่า “เช็กความเข้าใจ”คำถามชุดเดียวกันอยู่ใน quiz.yaml สำหรับระบบที่ตรวจอัตโนมัติ
-
เครื่องนับเสียงไอข้างเตียงผู้ป่วยควรเป็นแอปแบบใด (เลือกหนึ่งข้อ · เป้าหมายข้อ 1)
- ก) เมนูที่ให้ผู้ใช้เลือกโมเดลเองทุกครั้ง
- ข) แอปโฟกัสที่เล็งโมเดล Cough ตั้งแต่เปิด และต่อ verdict กับการนับ
- ค) แอปที่สลับทุกโมเดลทุกวินาที
- ง) ไม่ต้องมีแอป ใช้ REPL
เฉลย
ข — ผู้ใช้ปลายทางไม่ควรต้องรู้ว่ามีโมเดลอะไร เมนูเหมาะกับการสำรวจและเดโม แอปโฟกัสเหมาะกับงานจริง
-
ทำไม find_model((“cough”,), edge_ai.SENSOR_MIC) จึงดีกว่า edge_ai.select(3) (เลือกหนึ่งข้อ · เป้าหมายข้อ 2)
- ก) เร็วกว่า
- ข) หาโมเดลจากชื่อ จึงยังถูกตัวแม้ลำดับทะเบียนเปลี่ยน เช่น Emulator ที่ไม่มี Push ทำให้ Cough อยู่ index 2
- ค) ใช้หน่วยความจำน้อยกว่า
- ง) select(3) ใช้ไม่ได้บนบอร์ด
เฉลย
ข — บนบอร์ด Cough อยู่ index 3 แต่บน Emulator อยู่ index 2 การถามทะเบียนด้วยชื่อทำให้โค้ดชุดเดียวใช้ได้ทั้งสองที่
-
r[‘scores’] = [0.12, 0.88] ของโมเดล [‘unlabelled’, ‘cough’] ค่า r[‘top’] และ r[‘conf’] คืออะไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 3)
- ก) top = 0, conf = 0.12
- ข) top = 1, conf = 0.88
- ค) top = 0.88, conf = 1
- ง) top = 1, conf = 0.12
เฉลย
ข — top คือ index ของคะแนนสูงสุด (argmax) conf คือค่าคะแนนนั้นเอง คลาสที่ชนะจึงเป็น cough ด้วยความมั่นใจ 0.88
-
ไอหนึ่งครั้งยาวสามผลอนุมาน ได้ conf ของ cough เป็น 0.8, 0.9, 0.85 แล้วตกลง ตัวนับแบบขอบขาขึ้นเพิ่มกี่ครั้ง (เลือกหนึ่งข้อ · เป้าหมายข้อ 4)
- ก) 0
- ข) 1
- ค) 3
- ง) 2
เฉลย
ข — นับเฉพาะตอนเปลี่ยนจากไม่เข้าเป้าเป็นเข้าเป้า ตราบใดที่ยังค้างเหนือเกณฑ์จะไม่นับซ้ำ ไอหนึ่งครั้งจึงได้ 1
-
แอป Cough ทำงานดีมาสักพัก แล้วผลค้างนิ่งและ seq ไม่ขยับ สาเหตุที่น่าจะเป็นที่สุดคืออะไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 4)
- ก) โค้ดมี memory leak
- ข) โมเดล Ready-Model แบบประเมินผลถึงเพดานจำนวนครั้งอนุมาน
- ค) CONF_FLOOR ตั้งผิด
- ง) ไมค์เสีย
เฉลย
ข — โมเดลประเมินผลจำกัดจำนวนครั้งอนุมาน นี่คือลักษณะของใบอนุญาต ไม่ใช่บั๊กในโค้ด โมเดลที่ฝึกเองไม่มีข้อจำกัดนี้
- รัน
17_latency_min_max_avg.pyกับTARGET = "motion"แล้วเปลี่ยนเป็น"cough"จดต่ำสุด สูงสุด และเฉลี่ยของทั้งสองลงบันทึกการเรียน - เขียน
find_model()ด้วยมือในบันทึกการเรียน แล้วอธิบายว่าบน Emulator ที่ไม่มี Push ทำไมselect(3)จึงได้โมเดลคนละตัวกับบนบอร์ด - วาดกราฟ conf ของคลาส cough ตามเวลาแบบคร่าว ๆ แล้วทำเครื่องหมายจุดที่ต้องนับตามกฎขอบขาขึ้น
บทเรียน 6.2 เราจะเติม s15_apps.py ให้เป็นแอปนับเสียงไอ แล้วรีทาร์เก็ตเป็น Alarm หรือ Siren ด้วยการแก้แค่สองบรรทัดบนหัวไฟล์
บทเรียนถัดไป: บทเรียน 6.2 — ลงมือทำ: แอปโฟกัสของเราเอง
สะท้อนคิด
หัวข้อที่มีชื่อว่า “สะท้อนคิด”- อุปกรณ์รอบตัวคุณชิ้นไหนเป็นแอปโฟกัสโมเดลเดียว และมันทำ action อะไรกับ verdict
- ถ้าต้องเลือก CONF_FLOOR ให้เครื่องเตือนไซเรนในรถ คุณจะตั้งสูงหรือต่ำ เพราะอะไร
คำถามทบทวน
ลองตอบเองก่อน แล้วค่อยเปิดดูเฉลย
-
เครื่องนับเสียงไอข้างเตียงผู้ป่วยควรเป็นแอปแบบใด (เป้าหมายข้อ 1)
- เมนูที่ให้ผู้ใช้เลือกโมเดลเองทุกครั้ง
- แอปโฟกัสที่เล็งโมเดล Cough ตั้งแต่เปิด และต่อ verdict กับการนับ
- แอปที่สลับทุกโมเดลทุกวินาที
- ไม่ต้องมีแอป ใช้ REPL
ดูเฉลย
คำตอบ: B. แอปโฟกัสที่เล็งโมเดล Cough ตั้งแต่เปิด และต่อ verdict กับการนับ
ผู้ใช้ปลายทางไม่ควรต้องรู้ว่ามีโมเดลอะไร เมนูเหมาะกับการสำรวจและเดโม แอปโฟกัสเหมาะกับงานจริง
-
ทำไม find_model(("cough",), edge_ai.SENSOR_MIC) จึงดีกว่า edge_ai.select(3) (เป้าหมายข้อ 2)
- เร็วกว่า
- หาโมเดลจากชื่อ จึงยังถูกตัวแม้ลำดับทะเบียนเปลี่ยน เช่น Emulator ที่ไม่มี Push ทำให้ Cough อยู่ index 2
- ใช้หน่วยความจำน้อยกว่า
- select(3) ใช้ไม่ได้บนบอร์ด
ดูเฉลย
คำตอบ: B. หาโมเดลจากชื่อ จึงยังถูกตัวแม้ลำดับทะเบียนเปลี่ยน เช่น Emulator ที่ไม่มี Push ทำให้ Cough อยู่ index 2
บนบอร์ด Cough อยู่ index 3 แต่บน Emulator อยู่ index 2 การถามทะเบียนด้วยชื่อทำให้โค้ดชุดเดียวใช้ได้ทั้งสองที่
-
r['scores'] = [0.12, 0.88] ของโมเดล ['unlabelled', 'cough'] ค่า r['top'] และ r['conf'] คืออะไร (เป้าหมายข้อ 3)
- top = 0, conf = 0.12
- top = 1, conf = 0.88
- top = 0.88, conf = 1
- top = 1, conf = 0.12
ดูเฉลย
คำตอบ: B. top = 1, conf = 0.88
top คือ index ของคะแนนสูงสุด (argmax) conf คือค่าคะแนนนั้นเอง คลาสที่ชนะจึงเป็น cough ด้วยความมั่นใจ 0.88
-
ไอหนึ่งครั้งยาวสามผลอนุมาน ได้ conf ของ cough เป็น 0.8, 0.9, 0.85 แล้วตกลง ตัวนับแบบขอบขาขึ้นเพิ่มกี่ครั้ง (เป้าหมายข้อ 4)
- 0
- 1
- 3
- 2
ดูเฉลย
คำตอบ: B. 1
นับเฉพาะตอนเปลี่ยนจากไม่เข้าเป้าเป็นเข้าเป้า ตราบใดที่ยังค้างเหนือเกณฑ์จะไม่นับซ้ำ ไอหนึ่งครั้งจึงได้ 1
-
แอป Cough ทำงานดีมาสักพัก แล้วผลค้างนิ่งและ seq ไม่ขยับ สาเหตุที่น่าจะเป็นที่สุดคืออะไร (เป้าหมายข้อ 4)
- โค้ดมี memory leak
- โมเดล Ready-Model แบบประเมินผลถึงเพดานจำนวนครั้งอนุมาน
- CONF_FLOOR ตั้งผิด
- ไมค์เสีย
ดูเฉลย
คำตอบ: B. โมเดล Ready-Model แบบประเมินผลถึงเพดานจำนวนครั้งอนุมาน
โมเดลประเมินผลจำกัดจำนวนครั้งอนุมาน นี่คือลักษณะของใบอนุญาต ไม่ใช่บั๊กในโค้ด โมเดลที่ฝึกเองไม่มีข้อจำกัดนี้
อ้างอิงบทเรียนนี้
ถ้านำบทเรียนนี้ไปสอน ทำสไลด์ หรือทำเอกสารต่อ ให้อ้างอิงด้วยข้อความนี้ ถ้าดัดแปลงเนื้อหา ให้เติม (ดัดแปลง)ต่อท้ายชื่อบทเรียน
"หกโมเดลกับ edge_ai API: แอปที่โฟกัสโมเดลเดียว" จาก TESA Open Knowledge โดยสมาคมสมองกลฝังตัวไทย (Thai Embedded Systems Association: TESA) https://github.com/tesaiot/tesa-qualification-program สัญญาอนุญาต CC BY-NC 4.0
ข้อความอ้างอิงภาษาอังกฤษ: "Six models and the edge_ai API: an app focused on one model" from TESA Open Knowledge by the Thai Embedded Systems Association (TESA), https://github.com/tesaiot/tesa-qualification-program, licensed under CC BY-NC 4.0
ลิงก์บทเรียน: https://tesaiot.github.io/tesa-qualification-program/courses/edge-ai-developer/m06-apps/l01-focused-apps/
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0
เนื้อหาเผยแพร่ภายใต้ CC BY-NC 4.0 นำไปใช้ต่อในงานที่ไม่ใช่เพื่อการค้าได้ โปรดอ้างอิงสมาคมสมองกลฝังตัวไทย (TESA) ทุกครั้ง · วิธีอ้างอิง TESA