ข้ามไปยังเนื้อหา

ข้างในการฝึก: Keras, Conv1D, gradient descent, int8 และ confusion matrix

โมดูล 5 — ฝึกโมเดลและนำไปใช้หลายเป้าหมาย · สไลด์: slides.md · ภาพรวมโมดูล · หน้าหลักสูตร

เปิด train.py แกะสี่จังหวะ build, fit, convert และ eval พร้อมคณิตเบื้องหลัง ได้แก่สมการ Conv1D, softmax, cross-entropy, gradient descent และการบีบ int8 ด้วย scale กับ zero-point รู้ว่าทำไม representative dataset จำเป็น ทำไม normalization เป็นส่วนหนึ่งของโมเดล และอ่าน learning curve กับ confusion matrix ให้เป็น

เมื่อจบบทเรียนนี้ คุณจะ:

  1. คำนวณค่าออกของ Conv1D หนึ่งตำแหน่งด้วยมือจาก y[t] = Σ w[k]·x[t+k] + b และนับจำนวนพารามิเตอร์ของชั้น Conv1D กับ Dense ได้
  2. คำนวณ softmax ของคะแนนสามคลาส และแปลความ learning curve ว่าเป็นแบบดี overfit หรือ underfit
  3. อธิบายการบีบ int8 แบบ full-integer ด้วย real ≈ scale × (q − zero_point) และบอกหน้าที่ของ representative_dataset กับ inference_input_type
  4. อ่าน confusion matrix แล้วคำนวณความแม่นและระบุคู่คลาสที่โมเดลสับสนได้

ผ่านบทเรียน 5.3 มาแล้ว เคยรัน train.py และเห็น log ของมัน เปิด train.py คู่กับสไลด์ และถ้ามีเวลา ดาวน์โหลด math_lab.html มาเปิดในเบราว์เซอร์ (ต้องต่อเน็ตเพื่อโหลด GeoGebra)

train.py อ่านเป็นสี่จังหวะ build → fit → convert → eval จังหวะ build วางโมเดล 1-D CNN ด้วย tf.keras.Sequential: input (50, 6) → Conv1D(16, 5) → MaxPooling1D(2) → Conv1D(32, 3) → GlobalAveragePooling1D → Dense(32) → Dense(3, softmax) ทุกชั้นเป็น op ที่ Ethos-U55 เร่งได้ รวมราว 3,200 พารามิเตอร์ (Conv1D แรก 5·6·16 + 16 = 496) Conv1D คือ $y[t] = \sum_{k=0}^{K-1} w[k],x[t+k] + b$ filter หนึ่งอันเลื่อนไปตามเวลา ค่าออกสูงเมื่อช่วงนั้นหน้าตาเหมือน filter เช่น kernel [.2 .5 .3] บน .1 .4 .8 ได้ .46 (b = 0)

จังหวะ fit วนสามสมการทุก batch: softmax $\hat{y}_i = e^{z_i}/\sum_j e^{z_j}$ เปลี่ยนคะแนนดิบเป็นความน่าจะเป็นที่รวมกันได้ 1 cross-entropy $L = -\sum_i y_i \log \hat{y}i$ วัดว่าทายห่างเฉลยแค่ไหน และ gradient descent $\theta \leftarrow \theta - \eta,\nabla\theta L$ ขยับน้ำหนักลงเนินของ loss (adam คือ optimizer ตระกูลนี้) epochs=25, batch_size=32 และ validation_data ให้เราอ่าน learning curve: accuracy กับ val_accuracy ขึ้นด้วยกันคือดี train สูงแต่ val ต่ำหรือตกคือ overfit ทั้งคู่ต่ำค้างคือ underfit

จังหวะ convert บีบ float32 เป็น int8 ด้วย $real \approx scale \times (q - zero_point)$ เล็กลงราวสี่เท่าและ NPU เร่งได้ converter ต้อง calibrate ช่วงค่าของ activation จาก representative_dataset (หน้าต่างจริงจากชุดฝึก 200 อัน) ถ้าตั้ง TFLITE_BUILTINS_INT8 แต่ไม่ผูกชุดนี้ convert() จะหยุดด้วย ValueError ส่วน inference_input_type = tf.int8 และ inference_output_type = tf.int8 ทำให้ขาเข้าขาออกเป็น int8 ล้วน mean/std ของการ normalize ถูกเซฟลง .norm.npz เพราะ normalization เป็นส่วนหนึ่งของโมเดล ฝั่งที่ใช้ต้องใช้ค่าเดียวกัน จังหวะ eval quantize input ด้วย scale/zero-point ของไฟล์ รัน แล้ว dequantize ขาออกก่อน argmax ผลสรุปเป็น confusion matrix แถวคือคลาสจริง คอลัมน์คือคลาสที่ทาย แนวทแยงคือทายถูก ช่องนอกแนวทแยงบอกว่าต้องเก็บข้อมูลเพิ่มที่คู่ไหน

สไลด์ของบทเรียนนี้อ้างถึงไฟล์ที่อยู่ในบทเรียนอื่นหรือใน shared/ ด้วย:

คำถามชุดเดียวกันอยู่ใน quiz.yaml สำหรับระบบที่ตรวจอัตโนมัติ

  1. kernel w = [.2, .5, .3] และ b = 0 บนสัญญาณ .4 .8 .6 ได้ค่าออกเท่าไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 1)

    • ก) 0.46
    • ข) 0.52
    • ค) 0.66
    • ง) 1.80
    เฉลย

    ค — .2×.4 + .5×.8 + .3×.6 = .08 + .40 + .18 = .66 คือการคูณแล้วบวกทีละตำแหน่ง

  2. คะแนนดิบ z = [2.0, 3.1, 1.2] ของ idle, circle, shaking หลัง softmax circle ได้ความน่าจะเป็นราวเท่าไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 2)

    • ก) 0.31
    • ข) 0.49
    • ค) 0.67
    • ง) 1.00
    เฉลย

    ค — e^3.1 ≈ 22.2 หารด้วย e^2.0 + e^3.1 + e^1.2 ≈ 7.39 + 22.2 + 3.32 ≈ 32.9 ได้ราว 0.67 ส่วน idle ราว 0.22 และ shaking ราว 0.10

  3. ฝึกจบแล้ว accuracy = 0.99 แต่ val_accuracy = 0.60 และตกลงเรื่อย ๆ ในช่วงท้าย แปลว่าอะไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 2)

    • ก) โมเดลดีมาก
    • ข) overfit โมเดลจำชุดฝึกแต่ไม่ generalize
    • ค) underfit โมเดลเล็กเกินไป
    • ง) representative dataset ผิด
    เฉลย

    ข — train สูงแต่ val ไม่ตามคือจำข้อสอบ แก้ด้วยข้อมูลเพิ่ม หยุดเร็วขึ้น หรือโมเดลเล็กลง ส่วน underfit คือทั้งคู่ต่ำค้าง

  4. ตั้ง supported_ops = [TFLITE_BUILTINS_INT8] แต่ลืมผูก representative_dataset แล้วเรียก convert() จะเกิดอะไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 3)

    • ก) ได้ไฟล์ที่แม่นเท่าเดิม
    • ข) converter หยุดด้วย ValueError เพราะ full-integer ต้องมีตัวอย่างไว้ calibrate
    • ค) ได้ไฟล์ float32
    • ง) ไฟล์เล็กลงแปดเท่า
    เฉลย

    ข — ไม่มีตัวอย่าง converter ก็เลือก scale และ zero-point ของ activation ไม่ได้ TensorFlow จึงปฏิเสธตั้งแต่ต้น ถ้ามีแต่เป็นตัวอย่างที่ไม่เหมือนจริง ไฟล์จะออกมาแต่แม่นตก

  5. confusion matrix: idle [10 0 0], circle [0 8 2], shaking [0 1 9] ความแม่นและคู่ที่สับสนที่สุดคืออะไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 4)

    • ก) ความแม่น 0.90 และโมเดลทาย circle ผิดเป็น shaking บ่อยที่สุด
    • ข) ความแม่น 0.90 และโมเดลทาย idle ผิดบ่อยที่สุด
    • ค) ความแม่น 0.27 และไม่มีคู่ใดสับสน
    • ง) ความแม่น 1.00
    เฉลย

    ก — แนวทแยง 10 + 8 + 9 = 27 จาก 30 คือ 0.90 แถว circle มี 2 หน้าต่างที่ถูกทายเป็น shaking ควรเก็บสองท่านี้เพิ่ม

  • คำนวณค่าออก Conv1D อีกสามตำแหน่งของ kernel [.2 .5 .3] บน .1 .4 .8 .6 .2 .3 แล้วเทียบกับภาพเคลื่อนไหว
  • นับพารามิเตอร์ของทุกชั้นในโมเดลด้วยมือ แล้วเทียบกับ model.count_params() ที่ฉบับเต็มพิมพ์ออกมา
  • คำนวณ softmax ของ [2.0, 3.1, 1.2] และ loss เมื่อเฉลยคือ circle แล้วจดลงบันทึกการเรียน

บทเรียน 5.5 เราจะเติมสี่ช่องใน s12_train.py ให้ครบทั้งสี่จังหวะ แล้วรันใน Docker จนได้โมเดลของเราเอง

บทเรียนถัดไป: บทเรียน 5.5 — ลงมือทำ: เติมสคริปต์ฝึกแล้วรันใน Docker

  • ถ้า confusion matrix ของข้อมูลจริงสับสน circle กับ shaking บ่อย คุณจะแก้ที่ข้อมูลหรือที่โมเดลก่อน เพราะอะไร
  • ทำไมการ normalize ด้วย mean/std คนละชุดจึงเป็นบั๊กที่หายากกว่าโปรแกรม error

คำถามทบทวน

ลองตอบเองก่อน แล้วค่อยเปิดดูเฉลย

  1. kernel w = [.2, .5, .3] และ b = 0 บนสัญญาณ .4 .8 .6 ได้ค่าออกเท่าไร (เป้าหมายข้อ 1)

    1. 0.46
    2. 0.52
    3. 0.66
    4. 1.80
    ดูเฉลย

    คำตอบ: C. 0.66

    .2×.4 + .5×.8 + .3×.6 = .08 + .40 + .18 = .66 คือการคูณแล้วบวกทีละตำแหน่ง

  2. คะแนนดิบ z = [2.0, 3.1, 1.2] ของ idle, circle, shaking หลัง softmax circle ได้ความน่าจะเป็นราวเท่าไร (เป้าหมายข้อ 2)

    1. 0.31
    2. 0.49
    3. 0.67
    4. 1.00
    ดูเฉลย

    คำตอบ: C. 0.67

    e^3.1 ≈ 22.2 หารด้วย e^2.0 + e^3.1 + e^1.2 ≈ 7.39 + 22.2 + 3.32 ≈ 32.9 ได้ราว 0.67 ส่วน idle ราว 0.22 และ shaking ราว 0.10

  3. ฝึกจบแล้ว accuracy = 0.99 แต่ val_accuracy = 0.60 และตกลงเรื่อย ๆ ในช่วงท้าย แปลว่าอะไร (เป้าหมายข้อ 2)

    1. โมเดลดีมาก
    2. overfit โมเดลจำชุดฝึกแต่ไม่ generalize
    3. underfit โมเดลเล็กเกินไป
    4. representative dataset ผิด
    ดูเฉลย

    คำตอบ: B. overfit โมเดลจำชุดฝึกแต่ไม่ generalize

    train สูงแต่ val ไม่ตามคือจำข้อสอบ แก้ด้วยข้อมูลเพิ่ม หยุดเร็วขึ้น หรือโมเดลเล็กลง ส่วน underfit คือทั้งคู่ต่ำค้าง

  4. ตั้ง supported_ops = [TFLITE_BUILTINS_INT8] แต่ลืมผูก representative_dataset แล้วเรียก convert() จะเกิดอะไร (เป้าหมายข้อ 3)

    1. ได้ไฟล์ที่แม่นเท่าเดิม
    2. converter หยุดด้วย ValueError เพราะ full-integer ต้องมีตัวอย่างไว้ calibrate
    3. ได้ไฟล์ float32
    4. ไฟล์เล็กลงแปดเท่า
    ดูเฉลย

    คำตอบ: B. converter หยุดด้วย ValueError เพราะ full-integer ต้องมีตัวอย่างไว้ calibrate

    ไม่มีตัวอย่าง converter ก็เลือก scale และ zero-point ของ activation ไม่ได้ TensorFlow จึงปฏิเสธตั้งแต่ต้น ถ้ามีแต่เป็นตัวอย่างที่ไม่เหมือนจริง ไฟล์จะออกมาแต่แม่นตก

  5. confusion matrix: idle [10 0 0], circle [0 8 2], shaking [0 1 9] ความแม่นและคู่ที่สับสนที่สุดคืออะไร (เป้าหมายข้อ 4)

    1. ความแม่น 0.90 และโมเดลทาย circle ผิดเป็น shaking บ่อยที่สุด
    2. ความแม่น 0.90 และโมเดลทาย idle ผิดบ่อยที่สุด
    3. ความแม่น 0.27 และไม่มีคู่ใดสับสน
    4. ความแม่น 1.00
    ดูเฉลย

    คำตอบ: A. ความแม่น 0.90 และโมเดลทาย circle ผิดเป็น shaking บ่อยที่สุด

    แนวทแยง 10 + 8 + 9 = 27 จาก 30 คือ 0.90 แถว circle มี 2 หน้าต่างที่ถูกทายเป็น shaking ควรเก็บสองท่านี้เพิ่ม

อ้างอิงบทเรียนนี้

ถ้านำบทเรียนนี้ไปสอน ทำสไลด์ หรือทำเอกสารต่อ ให้อ้างอิงด้วยข้อความนี้ ถ้าดัดแปลงเนื้อหา ให้เติม (ดัดแปลง)ต่อท้ายชื่อบทเรียน

"ข้างในการฝึก: Keras, Conv1D, gradient descent, int8 และ confusion matrix" จาก TESA Open Knowledge โดยสมาคมสมองกลฝังตัวไทย (Thai Embedded Systems Association: TESA) https://github.com/tesaiot/tesa-qualification-program สัญญาอนุญาต CC BY-NC 4.0

ข้อความอ้างอิงภาษาอังกฤษ: "Inside training: Keras, Conv1D, gradient descent, int8 and the confusion matrix" 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/m05-training/l04-inside-training/

วิธีอ้างอิง TESA ฉบับเต็ม

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

เนื้อหาเผยแพร่ภายใต้ CC BY-NC 4.0 นำไปใช้ต่อในงานที่ไม่ใช่เพื่อการค้าได้ โปรดอ้างอิงสมาคมสมองกลฝังตัวไทย (TESA) ทุกครั้ง · วิธีอ้างอิง TESA