Machine Learning › Deep learning เบื้องต้น
Overfitting ของ neural network และเมื่อไรควรใช้ DL
ประมาณ 35 นาที
เป้าหมายของบท
- ลด overfitting ของ MLP ด้วย alpha, early_stopping และขนาดโมเดล
- รายงานผลของโมเดลสุ่มอย่างซื่อตรง (หลาย seed, ค่าเฉลี่ย ± std)
- ตัดสินใจได้ว่าเมื่อไรควรและไม่ควรใช้ deep learning
Neural network overfit ง่ายมาก
MLP มีพารามิเตอร์เป็นร้อยเป็นพัน — ให้เวลาเทรนนานพอก็ “จำ” ข้อมูลเทรนได้ ในข้อมูลของเรา MLP (16,) 200 รอบได้ train 0.7027 แต่ test 0.5986 (baseline 0.5901, logistic regression 0.6437) เครื่องมือควบคุมที่มีใน scikit-learn:
| วิธี | ตัวเลือก | ผลในข้อมูลนี้ (hidden 16, scale แล้ว) |
|---|---|---|
| L2 regularization | alpha (ค่าเริ่มต้น 0.0001) |
alpha 1.0: train 0.6914 / test 0.6169 · alpha 3.0: 0.6670 / 0.6408 |
| หยุดก่อนจำ | early_stopping=True (กัน 10% เป็น validation) |
หยุดที่รอบ 27, train 0.6538 / test 0.6282 |
| โมเดลเล็กลง | hidden_layer_sizes |
(4,) test 0.6324 · (8,) 0.6310 · (16,) 0.5986 · (16, 8) 0.5775 |
ทุกวิธีคือการลดความสามารถในการจำ — ช่องว่าง train−test แคบลง (และ test ดีขึ้นเล็กน้อย) (PyTorch/Keras มีตัวเลือกเพิ่ม เช่น dropout สุ่มปิด neuron ระหว่างเทรน)
from sklearn.neural_network import MLPClassifier
mlp = MLPClassifier(hidden_layer_sizes=(16,), alpha=1.0, early_stopping=True, random_state=42)
mlp.fit(Z_train, y_train)
mlp.n_iter_, mlp.best_validation_score_
ผลลัพธ์ขึ้นกับ seed
น้ำหนักเริ่มต้นสุ่ม ดังนั้น random_state ต่างกันให้ผลต่างกัน ทดสอบ 5 seed (0–4) บน test:
- ไม่ใช้ early stopping: 0.5972, 0.5873, 0.6141, 0.6127, 0.6296 (แกว่งประมาณ 0.04)
- ใช้ early stopping: 0.6479, 0.6423, 0.5944, 0.6352, 0.6155
ตัวเลขเดียวจาก seed เดียวจึงไม่น่าเชื่อถือ — รายงาน ค่าเฉลี่ยและ std ข้ามหลาย seed หรือใช้ cross-validation
เมื่อไรควรใช้ Deep Learning
ควรใช้ เมื่อข้อมูลเป็นรูปภาพ ข้อความ เสียง (ข้อมูลที่ไม่มีโครงสร้างตาราง) หรือมีข้อมูลจำนวนมหาศาล และใช้ pretrained model / transfer learning ตัวใหญ่ ผ่านเฟรมเวิร์กอย่าง PyTorch หรือ TensorFlow (รวมทั้ง GPU)
ไม่จำเป็น สำหรับข้อมูลตารางขนาดเล็ก–กลาง: gradient boosting หรือ logistic regression มักเทรนเร็วกว่า อธิบายได้ง่ายกว่า และแม่นเท่ากันหรือดีกว่า — ข้อมูลลูกค้าของเรา (2,839 แถว) เป็นตัวอย่างชัดเจน กฎง่ายๆ: เริ่มด้วย baseline → logistic regression → gradient boosting แล้วค่อยพิจารณา DL เมื่อมีเหตุผลเฉพาะ
ตัวอย่างแก้โจทย์
กด "ขั้นต่อไป" ทีละขั้น ลองรันและแก้โค้ดในแต่ละขั้นได้
ลด overfitting ด้วย alpha และ early stopping
เทียบ MLP (16,) แบบเดิม กับ alpha สูงและ early stopping
alpha = 1.0: train ลดเหลือ 0.6914 และ test เพิ่มเป็น 0.6169 (จาก 0.5986)
ความแกว่งข้าม seed
รันหลาย seed แล้วรายงานค่าเฉลี่ยและ std
MLP (16,) 5 seed (0–4) ไม่ใช้ early stopping: test 0.5873–0.6296 (ค่าเฉลี่ยราว 0.61)
เติมช่องว่าง
แทน ___ ด้วยโค้ดที่ถูกต้อง แล้วกดตรวจคำตอบ
fit MLP (16,) ที่เปิด early stopping (max_iter=200, random_state=42) แล้วเก็บจำนวน iteration ที่ใช้จริงไว้ใน stopped_at เติม ___ ให้ครบ
แบบฝึกท้ายบท
บทนี้จะนับว่าเสร็จเมื่อผ่านข้อพื้นฐานและประยุกต์ครบ ข้อท้าทายได้ดาวเพิ่ม
🟢 พื้นฐาน
MLP (16,) ที่ alpha=1.0 (max_iter=200, random_state=42): accuracy บน train และ test (ปัด 4 ตำแหน่ง) เก็บไว้ในตัวแปร alpha1_train, alpha1_test
MLP (16,) ที่เปิด early_stopping=True (max_iter=200, random_state=42): เก็บจำนวน iteration ที่ใช้ไว้ใน es_iters และ best_validation_score_ (ปัด 4 ตำแหน่ง) ไว้ใน es_best_val
accuracy บนชุดทดสอบของ MLP ตัวเดียวกับข้อ e2 (early stopping) ปัด 4 ตำแหน่ง เก็บไว้ในตัวแปร es_test_acc
MLP (16,) มีพารามิเตอร์กี่ตัวต่อแถวข้อมูลเทรน (จำนวนพารามิเตอร์ ÷ len(Z_train)) ปัด 4 ตำแหน่ง เก็บไว้ในตัวแปร params_per_row
🟡 ประยุกต์
accuracy บนชุดทดสอบของ MLP (16,) (max_iter=200, random_state=42) เมื่อ alpha = 0.0001, 1.0 และ 3.0 ปัด 4 ตำแหน่ง เก็บไว้ในตัวแปร acc_a0001, acc_a1, acc_a3
เทรน MLP (16,) (max_iter=200) ด้วย random_state = 0, 1, 2, 3, 4 (ไม่ใช้ early stopping) แล้วเก็บ accuracy บนชุดทดสอบของแต่ละ seed: ค่าเฉลี่ย (seed_mean) และ std (seed_std, np.std) ปัด 4 ตำแหน่ง
ทำเหมือนข้อ e6 แต่เปิด early_stopping=True: ค่าเฉลี่ยและ std ของ accuracy บนชุดทดสอบข้าม 5 seed (0–4) ปัด 4 ตำแหน่ง เก็บไว้ในตัวแปร es_seed_mean, es_seed_std
🔴 ท้าทาย
CV 5-fold (StratifiedKFold shuffle=True, random_state=42) บน X, y ทั้งชุด: accuracy เฉลี่ยของ pipeline StandardScaler + MLPClassifier(hidden (8,), early_stopping=True, max_iter=200, random_state=42) และของ StandardScaler + LogisticRegression(max_iter=2000) ปัด 4 ตำแหน่ง เก็บไว้ในตัวแปร mlp_cv, logreg_cv
เทียบ ROC-AUC บนชุดทดสอบของ MLP (16,) ที่ early_stopping=True (max_iter=200, random_state=42, บน Z_train/Z_test) กับ GradientBoostingClassifier(random_state=42) (บน X_train/X_test) ปัด 4 ตำแหน่ง เก็บไว้ใน mlp_auc, gb_auc และชื่อตัวที่ AUC สูงกว่า ("gb" หรือ "mlp") ไว้ใน winner
Quiz
สรุป
- MLP overfit ง่าย: alpha สูง (1.0: test 0.6169), early_stopping (หยุดที่รอบ 27, test 0.6282) หรือโมเดลเล็กลงช่วยลดช่องว่าง train−test
- ผลขึ้นกับ seed (test 0.5873–0.6296 ใน 5 seed) จึงต้องรายงานค่าเฉลี่ย ± std หรือใช้ CV
- ข้อมูลตารางขนาดเล็ก–กลางมักเหมาะกับ logistic regression / gradient boosting มากกว่า DL; DL เด่นกับรูปภาพ ข้อความ เสียง และข้อมูลขนาดใหญ่
คำถามสัมภาษณ์
จะทำอย่างไรถ้า neural network overfit ข้อมูลตาราง
ลดความจุของโมเดล (hidden layer เล็กลง), regularization (L2/alpha, dropout ใน framework อื่น), early stopping ด้วย validation set, เพิ่มข้อมูลหรือ augmentation ถ้าทำได้ และเทียบกับ baseline ง่ายๆ เช่น logistic regression/gradient boosting เสมอ เพราะบนข้อมูลตารางขนาดเล็กโมเดลง่ายมักดีเท่ากันหรือกว่า
เมื่อไรที่คุณจะเลือกใช้ deep learning แทน gradient boosting
เมื่อข้อมูลเป็นรูปภาพ ข้อความ เสียง หรือลำดับ (ที่ต้องเรียนรู้ representation เอง) เมื่อมีข้อมูลมหาศาล หรือมี pretrained model ให้ทำ transfer learning สำหรับข้อมูลตารางทั่วไป gradient boosting มักเป็นตัวเลือกแรกเพราะเร็ว แม่น และอธิบายง่ายกว่า