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

ลงมือทำ: เติมสคริปต์ฝึกแล้วรันใน Docker

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

เติมสี่ช่องใน s12_train.py ตรงสี่จังหวะของการฝึก คือ fit, representative dataset, int8 I/O และ accuracy แล้วรันใน Docker จนได้ model_int8.tflite กับรายงานความแม่น float32, int8 และ confusion matrix ของโมเดลที่เราฝึกเองทั้งตัว พร้อมทดลองลดจำนวน epoch และเปลี่ยนชุด calibrate

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

  1. เติมสี่ช่องใน practice/s12_train.py จนรันใน Docker ได้ float32 test accuracy, int8 test accuracy, confusion matrix และไฟล์ model_int8.tflite กับ .norm.npz
  2. รันเทียบ 3 epoch กับ 25 epoch แล้วจดความแม่นทั้งสองแบบ พร้อมอธิบายความต่างด้วยคำว่า underfit
  3. ระบุได้จากอาการว่าช่องใดยังว่าง (ความแม่นราว 0.33, ValueError ตอน convert, eval ป้อน int8 ไม่ผ่าน หรือ accuracy 0.000)

ผ่านบทเรียน 5.4 มาแล้ว เข้าใจสี่จังหวะ build, fit, convert, eval คัดลอก practice/s12_train.py ไปวางใน shared/training ข้าง dataset_tools.py และมี data/gestures.csv พร้อม

ไฟล์ฝึกให้ dataset_tools, build_model และส่วน quantize/dequantize ไว้ครบ เหลือสี่ช่องที่ตรงสี่จังหวะ: (1) ใน main() หลัง compile เติม model.fit(Xtr, ytr, validation_data=(Xva, yva), epochs=a.epochs, batch_size=32, verbose=2) ลืมช่องนี้ โมเดลไม่เคยเรียน ความแม่นจะอยู่แถว 0.33 (เดาในสามคลาส) (2) ใน to_int8_tflite() เติม conv.representative_dataset = representative ลืมแล้ว convert() หยุดด้วย ValueError (3) เติม conv.inference_input_type = tf.int8 และ conv.inference_output_type = tf.int8 ลืมแล้วขาเข้าขาออกยังเป็น float32 (สเกลใน quantization เป็น 0) และ eval_int8() ที่ป้อน int8 จะรันไม่ผ่าน (4) ใน eval_int8() เติม acc = (preds == yte).mean() ลืมแล้วรายงาน 0.000 ทั้งที่ confusion matrix อาจถูกทั้งแนวทแยง

รันด้วย docker run --rm -v "$PWD":/work edgeai-train python s12_train.py จะได้ float32 test accuracy → int8 test accuracy → confusion matrix และไฟล์ model_int8.tflite กับ model_int8.tflite.norm.npz ความสำเร็จไม่ใช่แค่เห็นตัวเลขวิ่ง แต่ต้องบอกได้ว่าทำไม int8 ควรใกล้ float32 และ representative dataset มีไว้ทำอะไร ไฟล์ที่ได้คือชิ้นงานที่ชุดบทเรียนถัดไปจะพาไปเบราว์เซอร์และบอร์ด

s12_train_full.py สร้างชุดสังเคราะห์ให้เองถ้ายังไม่มี data/gestures.csv พิมพ์ model.summary() กับ count_params() เตือนเมื่อ int8 แม่นตกจาก float32 เกิน INT8_DROP_WARN = 0.05 และมีเกต MVP ที่ผ่านเมื่อ int8 accuracy ≥ MVP_MIN_ACC = 0.80 (คืน exit code 0 หรือ 1 ใช้ใน CI ได้) วางไว้ใน shared/training เช่นเดียวกับไฟล์ฝึก

ไฟล์ ไฟล์นี้สอน
examples/s12_train_full.py ฝึก + ทดสอบโมเดลท่ามือ แบบครบวงจร (ฉบับเต็ม)

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

คอมเมนต์ # เติม: อยู่ที่บรรทัด 131 (ช่อง 1 model.fit), 53 (ช่อง 2 representative_dataset), 60 (ช่อง 3 int8 I/O) และ 97 (ช่อง 4 acc) เติมทีละช่องแล้วรัน อาการของช่องที่ยังว่างบอกได้เองว่าเหลือช่องไหน

ไฟล์ฝึก เรื่อง
practice/s12_train.py ฝึกโมเดลของเราเองด้วย TensorFlow แล้วทดสอบบน PC (ฉบับฝึกเติมโค้ด)

เปิดเฉลยหลังจากลองเองแล้วอย่างน้อยหนึ่งรอบ และอ่าน วิธีใช้เฉลย ก่อน

เฉลย คู่กับ
solution/s12_train.py practice/s12_train.py

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

  1. รันแล้วได้ float32 test accuracy: 0.333 ทุกครั้ง ช่องใดยังว่าง (เลือกหนึ่งข้อ · เป้าหมายข้อ 1)

    • ก) ช่อง 1 model.fit
    • ข) ช่อง 2 representative_dataset
    • ค) ช่อง 3 int8 I/O
    • ง) ช่อง 4 acc
    เฉลย

    ก — ถ้าไม่ fit น้ำหนักยังเป็นค่าสุ่ม โมเดลเดาในสามคลาสได้ราวหนึ่งในสาม evaluate จึงวัดได้ราว 0.33

  2. convert() หยุดด้วย ValueError: For full integer quantization, a representative_dataset must be specified. ต้องแก้ช่องใด (เลือกหนึ่งข้อ · เป้าหมายข้อ 3)

    • ก) ช่อง 1
    • ข) ช่อง 2 เติม conv.representative_dataset = representative
    • ค) ช่อง 3
    • ง) ช่อง 4
    เฉลย

    ข — ข้อความบอกตรง ๆ ว่าการบีบแบบ full-integer ต้องมีตัวอย่างไว้ calibrate ช่วงค่า

  3. รายงานบอก int8 test accuracy: 0.000 แต่ confusion matrix มีตัวเลขเต็มแนวทแยง ช่องใดยังว่าง (เลือกหนึ่งข้อ · เป้าหมายข้อ 3)

    • ก) ช่อง 1
    • ข) ช่อง 2
    • ค) ช่อง 3
    • ง) ช่อง 4 acc ยังเป็นค่าเริ่มต้น 0.0
    เฉลย

    ง — confusion matrix คำนวณจาก preds จริง แต่ตัวเลขความแม่นมาจาก acc ที่ยังเป็น 0.0 ต้องเติม acc = (preds == yte).mean()

  4. ฝึก 3 epoch ได้ทั้ง accuracy และ val_accuracy ต่ำกว่าตอน 25 epoch ชัดเจน อธิบายอย่างไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 2)

    • ก) overfit
    • ข) underfit เพราะฝึกสั้นเกินไป loss ยังลงไม่สุด
    • ค) int8 ทำให้แม่นตก
    • ง) ข้อมูลรั่ว
    เฉลย

    ข — ทั้ง train และ val ต่ำด้วยกันคืออาการ underfit ให้เวลาโมเดลไถลลงเนิน loss มากขึ้นก็ดีขึ้น

MVP ของชุดบทเรียน 5.3–5.5: ฝึกโมเดล Keras ใน Docker สำเร็จ ได้รายงาน float32 accuracy, int8 accuracy และ confusion matrix บนชุดทดสอบที่โมเดลไม่เคยเห็น พร้อมไฟล์ model_int8.tflite และ .norm.npz

  • เติมไฟล์ฝึกครบสี่ช่อง รันใน Docker จนได้รายงานและไฟล์ทั้งสอง
  • รันด้วย --epochs 3 เทียบกับ 25 epoch จดความแม่นทั้งสองแบบลงบันทึกการเรียน และอธิบายความต่าง
  • ให้ representative() ป้อนหน้าต่างศูนย์ล้วน (np.zeros_like(X_repr[i:i + 1])) แทนหน้าต่างจริง แล้วเทียบ int8 accuracy กับเดิม
  • อธิบายได้ว่า fit, representative_dataset, inference_input_type และ accuracy อยู่ตรงไหน ทำอะไร

ชุดบทเรียนถัดไป (บทเรียน 5.6–5.7) เราจะพาไฟล์นี้ไปรันในเบราว์เซอร์ พิสูจน์ว่าคำตัดสินตรงกับ PC และเล่าเรื่องการรันบน Cortex-A

บทเรียนถัดไป: บทเรียน 5.6 — รันโมเดลบนเว็บ: LiteRT.js, int8 I/O และ parity

  • int8 accuracy ของคุณต่างจาก float32 เท่าไร และคุณเชื่อตัวเลขนั้นแค่ไหนเมื่อชุดทดสอบมีแค่ราวยี่สิบหน้าต่าง
  • ถ้าข้อมูลจริงให้ความแม่นต่ำกว่าข้อมูลสังเคราะห์มาก คุณจะเริ่มแก้จากตรงไหน

คำถามทบทวน

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

  1. รันแล้วได้ float32 test accuracy: 0.333 ทุกครั้ง ช่องใดยังว่าง (เป้าหมายข้อ 1)

    1. ช่อง 1 model.fit
    2. ช่อง 2 representative_dataset
    3. ช่อง 3 int8 I/O
    4. ช่อง 4 acc
    ดูเฉลย

    คำตอบ: A. ช่อง 1 model.fit

    ถ้าไม่ fit น้ำหนักยังเป็นค่าสุ่ม โมเดลเดาในสามคลาสได้ราวหนึ่งในสาม evaluate จึงวัดได้ราว 0.33

  2. convert() หยุดด้วย ValueError: For full integer quantization, a representative_dataset must be specified. ต้องแก้ช่องใด (เป้าหมายข้อ 3)

    1. ช่อง 1
    2. ช่อง 2 เติม conv.representative_dataset = representative
    3. ช่อง 3
    4. ช่อง 4
    ดูเฉลย

    คำตอบ: B. ช่อง 2 เติม conv.representative_dataset = representative

    ข้อความบอกตรง ๆ ว่าการบีบแบบ full-integer ต้องมีตัวอย่างไว้ calibrate ช่วงค่า

  3. รายงานบอก int8 test accuracy: 0.000 แต่ confusion matrix มีตัวเลขเต็มแนวทแยง ช่องใดยังว่าง (เป้าหมายข้อ 3)

    1. ช่อง 1
    2. ช่อง 2
    3. ช่อง 3
    4. ช่อง 4 acc ยังเป็นค่าเริ่มต้น 0.0
    ดูเฉลย

    คำตอบ: D. ช่อง 4 acc ยังเป็นค่าเริ่มต้น 0.0

    confusion matrix คำนวณจาก preds จริง แต่ตัวเลขความแม่นมาจาก acc ที่ยังเป็น 0.0 ต้องเติม acc = (preds == yte).mean()

  4. ฝึก 3 epoch ได้ทั้ง accuracy และ val_accuracy ต่ำกว่าตอน 25 epoch ชัดเจน อธิบายอย่างไร (เป้าหมายข้อ 2)

    1. overfit
    2. underfit เพราะฝึกสั้นเกินไป loss ยังลงไม่สุด
    3. int8 ทำให้แม่นตก
    4. ข้อมูลรั่ว
    ดูเฉลย

    คำตอบ: B. underfit เพราะฝึกสั้นเกินไป loss ยังลงไม่สุด

    ทั้ง train และ val ต่ำด้วยกันคืออาการ underfit ให้เวลาโมเดลไถลลงเนิน loss มากขึ้นก็ดีขึ้น

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

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

"ลงมือทำ: เติมสคริปต์ฝึกแล้วรันใน Docker" จาก TESA Open Knowledge โดยสมาคมสมองกลฝังตัวไทย (Thai Embedded Systems Association: TESA) https://github.com/tesaiot/tesa-qualification-program สัญญาอนุญาต CC BY-NC 4.0

ข้อความอ้างอิงภาษาอังกฤษ: "Hands-on: complete the training script and run it in Docker" 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/l05-train-lab/

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

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

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