บทเรียน 4.5 — feature และหน้าต่าง: สิ่งที่โมเดลเห็นจริง

สิ่งที่โมเดล "เห็น" จริง ๆ

โมดูล 4 — วิเคราะห์สัญญาณ

โมดูล 4 (Analysis, Pillar 3) — ชุดบทเรียนที่สาม

คาถาประจำบทเรียน: "โมเดลไม่เคยเห็นสัญญาณดิบ มันเห็นแต่ feature vector ที่เราบีบมาให้ — วันนี้เราจะเป็นคนบีบเอง"

MicroPython บนบอร์ด BENTO (PSoC Edge · Cortex-M55 + Ethos-U55 NPU)

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

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

เหมือนทุกบทเรียน เราเริ่มแบบ กลับด้าน — รันของที่ทำงานได้จริงก่อน แล้วค่อยแกะว่ามันบีบสัญญาณเป็นอะไร

รันตัวอย่างก่อน s10_windowing แกะดูข้างใน window + feature เติม/แก้เอง 5 จุดหลัก ต่อยอด สู่ Training

เปิด s10_windowing.py แล้ว Run ก่อนเลย — วางบอร์ดนิ่ง สลับกับเขย่าเบา ๆ แล้วดูแท่ง mean/std/band0..3 ขยับ นั่นแหละคือ feature vector ที่กำลังไหลเข้าโมเดล

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

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

เราอยู่ตรงไหนของวงจร

วันนี้เป็นชุดบทเรียนที่สามของ Analysis (Pillar 3) — ขั้นที่ 3 ของวงจรชีวิตข้อมูล เป็นจุดที่สัญญาณกลายเป็น "สิ่งที่โมเดลกินได้"

1 · DAQ โมดูล 2 2 · Processing โมดูล 3 3 · Analysis 4.1–4.2·4.3–4.4·4.5–4.6 (นี่) feature front-end 4 · Training โมดูล 5 5 · Apps โมดูล 6 Analysis คือประตูสุดท้ายก่อนสัญญาณจะกลายเป็นข้อมูลที่โมเดลกินได้

บทเรียน 4.1–4.2 เราขัดสัญญาณให้สะอาด (filter) · บทเรียน 4.3–4.4 เราแปลงไปโดเมนความถี่ (FFT) · วันนี้ บทเรียน 4.5–4.6 เราเอาสองอันนั้นมาบีบเป็น feature vector ที่โมเดลใช้จริง

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

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

จบชุดบทเรียนนี้เราจะเดินครบ 4 เรื่อง แล้วปิดท้ายด้วยการทำ feature front-end ด้วยมือเอง:

  1. ทำไมโมเดลไม่กิน sample ดิบ ทีละจุด แต่กิน "หน้าต่าง" (window) ของสัญญาณ
  2. Windowing + hop — ตัดสัญญาณเป็นหน้าต่างซ้อนกัน ทำไมต้องซ้อน (overlap)
  3. Feature vector — บีบหน้าต่างเป็นตัวเลขไม่กี่ตัว (mean, std, พลังงานต่อย่าน) และญาติของมันคือ mel/log-mel spectrogram ที่โมเดลเสียงใช้
  4. ลงมือ: สร้าง feature vector จากสัญญาณ IMU ด้วยตัวเอง แล้วดูมันขยับสดบนจอ

ปลายทางของวันนี้: จากสัญญาณ IMU ดิบ 50 จุด สร้าง feature vector 6 ตัวที่ เปลี่ยนตามการเคลื่อนไหวจริง ขึ้นจอ

วันนี้เราไม่ฝึกโมเดลนะ เราสร้าง "สิ่งที่โมเดลจะเห็น" ต่างหาก — พอถึงบทเรียน Training (บทเรียน 5.1–5.2) คุณจะเก็บ feature vector พวกนี้เป็น dataset จริง

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

ปัญหา: โมเดลไม่กิน sample ดิบทีละจุด

ลองนึกถึงเสียง "ไอ" หนึ่งครั้ง หรือท่า "เขย่า" หนึ่งที — มันไม่ใช่ค่า ณ จุดเดียว มันคือ รูปร่างของสัญญาณช่วงเวลาหนึ่ง

  • ถ้าป้อน accel ทีละจุดให้โมเดล มันเห็นแค่ตัวเลขเดียว บอกอะไรไม่ได้ว่ากำลัง "เขย่า" หรือ "นิ่ง"
  • ความหมายอยู่ใน แพตเทิร์นตามเวลา — ต้องดูสัญญาณเป็นก้อน ไม่ใช่ทีละจุด
  • เราจึงรวบสัญญาณเป็น "หน้าต่าง" (window) เช่น 50 จุด (= 1 วินาทีที่ 50 Hz) แล้วค่อยตัดสินใจจากทั้งก้อน
สัญญาณดิบ (ทีละจุด) — มองไม่ออกว่าเกิดอะไร: มองเป็น "ก้อน" (window) ถึงจะเห็นว่านี่คือ "เขย่า"

นี่คือหลักเดียวกับหูคน: เราแยก "เสียงไอ" กับ "เสียงพูด" ไม่ได้จากคลื่นเสียง 1/1000 วินาที ต้องฟังทั้งช่วงถึงจะรู้ โมเดลก็เหมือนกัน

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

ภาพเคลื่อนไหว — หน้าต่างเลื่อน (sliding window)

ภาพเคลื่อนไหว: kernel ของ Conv1D ไถลไปตามสัญญาณทีละตำแหน่ง แล้วคูณรวมเป็นผลลัพธ์ y[t]

หน้าต่างเลื่อนทีละก้าว (stride) บีบ sample หลายจุดให้เป็น feature หนึ่งชุดที่โมเดลกินได้

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

Windowing คืออะไร

Windowing คือการตัดสัญญาณที่ไหลมาเรื่อย ๆ ให้เป็นก้อนความยาวคงที่ (WIN จุด) ทีละก้อน แล้วประมวลผลทีละหน้าต่าง

สตรีมสัญญาณต่อเนื่อง → window 1 (WIN=50) window 2 window 3 แต่ละหน้าต่างเลื่อนไปทีละ HOP=25 จุด (ครึ่งหนึ่งของ WIN → ซ้อนกัน 50%) ทุกหน้าต่าง → คำนวณ feature หนึ่งชุด
  • WIN = 50 — ยาวหนึ่งหน้าต่าง (1 วินาทีที่ 50 Hz)
  • HOP = 25 — เลื่อนหน้าต่างทีละ 25 จุด (ครึ่งหนึ่งของ WIN)
  • ผลคือหน้าต่างซ้อนกัน 50% — เราจะได้ feature vector ชุดใหม่ทุก ๆ 25 จุด

ค่าพวกนี้ไม่ได้ตั้งมั่ว โมเดลถูกฝึกมาด้วยขนาดหน้าต่างเท่าไร ตอนใช้งานจริงก็ต้อง feed หน้าต่างขนาดเดียวกัน ไม่งั้น "สิ่งที่โมเดลเห็น" จะไม่ตรงกับตอนฝึก

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

ทำไมต้องซ้อน (overlap / hop)

ถ้าตัดหน้าต่างชนกันพอดี (hop = win) เหตุการณ์สั้น ๆ อาจตกร่องระหว่างหน้าต่างพอดีจนพลาด — การซ้อนช่วยไม่ให้พลาด

ไม่ซ้อน (hop = win) เหตุการณ์สั้นตกร่องระหว่างหน้าต่าง → พลาด ซ้อน 50% (hop = win/2) ทุกจุดถูกครอบด้วยหน้าต่างอย่างน้อยหนึ่งอัน → ไม่พลาด
  • ตอบไวขึ้น — ได้ผลใหม่ทุก HOP จุด ไม่ต้องรอครบทั้งหน้าต่างใหม่
  • ไม่พลาดเหตุการณ์สั้น — เสียงไอครั้งเดียว/ท่าปัดเร็ว ไม่หลุดร่องระหว่างหน้าต่าง
  • แต่ซ้อนมาก = คำนวณบ่อยขึ้น = กินแรงขึ้น เป็นข้อแลกเปลี่ยนที่วิศวกรต้องเลือก

hop เล็ก = ตอบไว แต่เปลือง · hop ใหญ่ = ประหยัด แต่ตอบช้าและอาจพลาด — เราเลือก 50% เป็นค่ากลางที่โมเดลเสียง/IMU ส่วนใหญ่ใช้

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

Feature vector — บีบหน้าต่างเป็นตัวเลขไม่กี่ตัว

หน้าต่างหนึ่งมี 50 จุด แต่เราไม่ได้ป้อน 50 จุดนั้นตรง ๆ เข้าโมเดล เราบีบมันเป็น feature vector สั้น ๆ ที่สรุป "ลักษณะเด่น" ของหน้าต่างไว้

หน้าต่าง 50 จุด บีบ (feature extraction) mean · std พลังงาน 4 ย่าน feature vector [m, s, b0, b1, b2, b3] 6 ตัว = สิ่งที่โมเดลเห็น
  • 50 จุด → 6 ตัวเลข: บีบข้อมูล ให้เล็กลงมาก แต่เก็บลักษณะสำคัญไว้
  • โมเดลเรียนรู้จาก 6 ตัวนี้ — ยิ่ง feature ดี โมเดลยิ่งเล็กและแม่นได้ (นี่คือหัวใจของ Edge AI)

"โมเดลดีแค่ไหน ขึ้นกับ feature ที่ป้อนมันมากพอ ๆ กับตัวโมเดลเอง" — วิศวกร Edge AI ใช้เวลากับ feature front-end นี้เยอะกว่าที่คนคิด

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

feature ที่เราคำนวณวันนี้

ตัวอย่างวันนี้บีบหนึ่งหน้าต่าง (แกน Z ของ accel) เป็น 6 ตัว สองกลุ่ม:

feature สูตร (ในโค้ด) บอกอะไร
mean sum(win)/n ระดับ DC / ทิศแรงโน้มถ่วงของแกนนี้
std sqrt(Σ(x-mean)²/n) ความแรงของการสั่น — นิ่ง=ต่ำ เขย่า=สูง
band0..3 variance ของแต่ละช่วงเวลา การสั่นกระจุกอยู่ต้น/กลาง/ท้ายหน้าต่าง
  • mean กับ std เป็น feature เชิงสถิติ ของทั้งหน้าต่าง — เบา คำนวณเร็ว แต่ทรงพลัง
  • band0..3 แบ่งหน้าต่างเป็น 4 ช่วงเวลาแล้ววัด variance แต่ละช่วง — จับ "รูปร่างตามเวลา" ได้หยาบ ๆ

std ตัวเดียวแยก "นิ่ง/ขยับ" ได้เกือบหมดแล้ว — ในฉบับเต็มเราเอา std มาตัดสิน "นิ่ง/ขยับ" ตรง ๆ เป็นตัวอย่างของ "การจำแนกคลาสเวอร์ชันมือทำ"

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

std คือหัวใจ — ทำไม variance ถึงเล่าเรื่องได้

std (ส่วนเบี่ยงเบนมาตรฐาน) วัดว่าสัญญาณ "แกว่ง" ห่างจากค่าเฉลี่ยแค่ไหน — มันคือรากของ variance ที่เราเจอมาตั้งแต่โมดูล 3 (Processing)

std=1n∑i=1n(xi−xˉ)2\mathrm{std} = \sqrt{\frac{1}{n}\sum_{i=1}^{n}(x_i - \bar{x})^2}

  • บอร์ดวางนิ่ง: ทุกจุดใกล้ค่าเฉลี่ย → std เล็ก
  • เขย่าบอร์ด: จุดกระจายห่างค่าเฉลี่ย → std ใหญ่
  • นี่คือเหตุผลที่ feature เชิงสถิติง่าย ๆ แยกท่าทางได้ดีอย่างน่าประหลาดใจ
นิ่ง → std ต่ำ เขย่า → std สูง

จำ variance จากบทเรียน Processing (บทเรียน 3.1–3.2) ได้ไหม — วันนี้เราเอามันกลับมาใช้เป็น feature โดยตรง แนวคิดเก่าไม่เคยหายไป มันแค่เปลี่ยนบทบาท

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

band energy — ญาติหยาบ ๆ ของ spectrogram

band0..3 แบ่งหน้าต่างเป็น 4 ช่วงเวลา แล้ววัดพลังงาน (variance) แต่ละช่วง — จับได้ว่าการสั่นแรงตอนไหนของหน้าต่าง

  • ถ้าการปัดมือเกิดตอนต้นหน้าต่าง → band0 แรง, band3 เบา
  • ถ้าเป็นการสั่นสม่ำเสมอ → ทุก band ใกล้กัน
  • นี่คือ "รูปร่างตามเวลา" แบบหยาบ — โมเดลใช้แยกท่าที่มี pattern เวลาต่างกันได้

ในโลกจริงของ เสียง เราไม่แบ่งตามเวลาอย่างเดียว เราแบ่งตาม ความถี่ (เอา FFT จาก บทเรียน 4.3–4.4 มาจัดเป็นย่าน) — นั่นแหละคือ mel spectrogram ที่หน้าถัดไปจะเล่า

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

สิ่งที่โมเดลเสียงเห็นจริง — mel / log-mel spectrogram

โมเดลเสียงบนบอร์ด (Baby Cry, Cough, Alarm, Siren) ไม่ได้กินคลื่นเสียงดิบ มันกิน spectrogram — ภาพความถี่ต่อเวลา

เสียงดิบ PDM / PCM ตัดหน้าต่าง win + hop (เหมือนวันนี้) FFT ต่อหน้าต่าง พลังงานต่อความถี่ (4.3–4.4) จัดเป็น mel band รวมเป็นไม่กี่ย่าน + log spectrogram = input โมเดล โครงเดียวกับที่เราทำวันนี้ ต่างแค่ "ย่าน" เป็นความถี่ (mel) แทนเวลา และมี log
  • mel band = จัดกลุ่มความถี่ให้ตรงกับที่หูคนได้ยิน (ความถี่ต่ำละเอียด ความถี่สูงหยาบ)
  • log = บีบช่วง dynamic range ให้เสียงเบา/ดังอยู่ในสเกลใกล้กัน
  • แต่แกนหลักเหมือนกันเป๊ะ: window → transform → รวมเป็นย่าน → นั่นคือ input ของโมเดล

วันนี้เราทำเวอร์ชัน IMU ที่เห็นด้วยตาง่ายกว่า แต่พอเข้าใจ "window → feature" แล้ว spectrogram ของเสียงก็คือเรื่องเดียวกัน แค่ย่านเป็นความถี่

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

คณิตของหน้าต่าง — Hann window

ก่อนเอาหน้าต่างไปทำ FFT เราไม่ตัดขอบตรง ๆ แต่ค่อย ๆ ลดขอบให้เรียบ ด้วยตัวคูณรูประฆังที่ชื่อ Hann window:

w[n]=0.5−0.5cos⁡ ⁣(2πnN−1)w[n] = 0.5 - 0.5\cos\!\left(\frac{2\pi n}{N-1}\right)

อ่านสัญลักษณ์ทีละตัวแบบง่าย ๆ:

  • nn — ลำดับจุดในหน้าต่าง เริ่มที่ 00 ไปจนถึง N−1N-1
  • NN — จำนวนจุดทั้งหน้าต่าง (เช่น WIN = 50)
  • w[n]w[n] — ตัวคูณของจุดที่ nn มีค่าอยู่ระหว่าง 00 (ที่ขอบสองข้าง) ถึง 11 (ตรงกลาง)

ค่าที่ได้: ขอบซ้าย w[0]=0w[0]=0 · กลางหน้าต่าง w≈1w \approx 1 · ขอบขวา w[N−1]=0w[N-1]=0 — เหมือนกดเสียงให้เบาลงตอนต้นและปลาย

1 0 n=0 n=N-1 w[n] — รูประฆัง Hann

ทำไมสำคัญกับชุดบทเรียนนี้: ตอนตัดหน้าต่างแข็ง ๆ ขอบที่ขาดกระทันหันจะสร้างความถี่ปลอมใน FFT (เรียก spectral leakage) พอคูณ Hann ให้ขอบค่อย ๆ จางลง สเปกตรัมสะอาดขึ้น — mel spectrogram ของเสียงทุกตัวบนบอร์ดใช้ trick นี้ก่อนทำ FFT เสมอ

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

คณิตของ spectrogram — log-mel

รวมทุกอย่างในหน้าที่แล้วเป็นสูตรเดียว คือสิ่งที่โมเดลเสียง "เห็น" จริง ๆ:

logmel=log⁡( Mel( ∣ FFT(x⋅w) ∣ ))\text{logmel} = \log\Big(\,\mathrm{Mel}\big(\,\lvert\,\mathrm{FFT}(x \cdot w)\,\rvert\,\big)\Big)

ไล่จากในสุดออกมานอกสุด — อ่านเหมือนสายพาน:

  • x⋅wx \cdot w — สัญญาณหนึ่งหน้าต่าง xx คูณ Hann window ww (ลดขอบให้เรียบก่อน)
  • FFT(⋅)\mathrm{FFT}(\cdot) — แปลงไปโดเมนความถี่ (ของ บทเรียน 4.3–4.4) ได้พลังงานต่อความถี่
  • ∣⋅∣\lvert\cdot\rvert — เอาขนาด (magnitude) ทิ้งเฟส เหลือแค่ "แต่ละความถี่แรงแค่ไหน"
  • Mel(⋅)\mathrm{Mel}(\cdot) — รวมความถี่เป็นไม่กี่ย่านตามสเกลการได้ยินของหู (ต่ำละเอียด สูงหยาบ)
  • log⁡(⋅)\log(\cdot) — บีบช่วง dynamic range ให้เสียงเบากับดังอยู่สเกลใกล้กัน
x · w FFT | · | Mel log

ทำไมสำคัญกับชุดบทเรียนนี้: band0..3 ที่เราทำวันนี้คือรุ่นย่อของสูตรนี้ — เราแบ่งเป็นย่านเวลาและวัด variance ส่วนเสียงแบ่งเป็นย่านความถี่ (Mel) แล้วใส่ log แค่นั้น โครง window → transform → รวมย่าน อันเดียวกันเป๊ะ

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

สิ่งที่โมเดลเห็น = feature vector ไม่ใช่สัญญาณดิบ

จับใจความสำคัญที่สุดของชุดบทเรียนนี้ให้แน่น:

โมเดลไม่เคยเห็นสัญญาณดิบ · มันเห็นแต่ feature vector ที่ front-end บีบมาให้
  • ตอน ฝึก (Training): dataset ก็คือชุดของ feature vector แบบนี้ พร้อม label
  • ตอน ใช้งาน (Apps): front-end บนบอร์ดบีบสัญญาณสดเป็น feature vector ชุดเดียวกัน แล้วป้อนโมเดล
  • ถ้า front-end ตอนฝึกกับตอนใช้ ไม่ตรงกัน โมเดลจะเพี้ยนทันที — นี่คือบั๊กคลาสสิกของ Edge AI

เพราะฉะนั้นการเข้าใจ feature front-end จึงสำคัญพอ ๆ กับตัวโมเดล — ชุดบทเรียนนี้คือรากฐานที่ทำให้โมดูล 5 (Training) ไม่ใช่กล่องดำ

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

รู้จักคำสั่งที่ใช้ในไฟล์วันนี้

ไฟล์ตัวอย่างใช้ของที่เราคุ้นแล้ว บวก math เข้ามาช่วยคำนวณ:

คำสั่ง ทำอะไร
sensors.bmi270.motion() คืน (ax,ay,az,gx,gy,gz) — เราใช้ az เป็นสัญญาณ
math.sqrt(x) รากที่สอง (สำหรับ std)
ui.Bar(...) / .value(v) แท่งแสดงค่า feature แต่ละตัว
ui.Label(...) / .text(s) ป้ายชื่อ feature + ตัวนับหน้าต่าง
lcd.console(...) พิมพ์ feature vector เป็นข้อความ (ดูค่าจริง)
time.sleep_ms(20) เว้นจังหวะให้ได้อัตราสุ่ม 50 Hz
  • ไม่มีคำสั่งใหม่แปลก ๆ — ชุดบทเรียนนี้ความยากอยู่ที่ แนวคิด (window/feature) ไม่ใช่ API
  • ทุกอย่างเป็น pure Python บน CM33 ไม่ต้องพึ่ง NPU เลย

sensors.bmi270.motion() คืน 6 ค่า เราแตกเป็น ax,ay,az,gx,gy,gz แล้วหยิบแค่ az มาทำสัญญาณตัวอย่าง — แกนอื่นทำแบบเดียวกันได้หมด

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