01Overall Concept
ไอเดียหลัก — Bagging สร้างโมเดลหลายตัวจากตัวอย่างข้อมูลคนละชุด แล้วให้ทุกตัวช่วยกันตอบ การรวมหลายความเห็นช่วยลดโอกาสที่ความบังเอิญในข้อมูลชุดเดียวจะพาโมเดลไปผิดทาง
ลองนึกภาพว่า — เหมือนให้เพื่อนหลายคนอ่านโจทย์จากแบบฝึกหัดที่สุ่มมาไม่เหมือนกัน แล้วขอให้ทุกคนลงคะแนนคำตอบ เสียงรวมมักนิ่งกว่าการเชื่อเพื่อนเพียงคนเดียว
ตัวอย่างการนำไปใช้ — ทำให้ Decision Tree ทำนายเสถียรขึ้น ลดความผันผวนของโมเดล หรือสร้างคำตอบรวมจากผู้เรียนหลายตัว
02อธิบายภาษาคนเข้าใจง่ายๆ
Bagging ย่อมาจาก Bootstrap Aggregating
ชื่อฟังดูน่ากลัว แต่แนวคิดง่ายมาก
สมมติเรามีข้อมูลลูกค้า 10,000 คน
แทนที่จะสร้างโมเดลเดียว เราสุ่มข้อมูลออกมาเป็นหลายชุด
ชุด A ชุด B ชุด C ...
แล้วสร้างโมเดลหนึ่งตัวจากแต่ละชุด
สมมติสร้าง 100 โมเดล
ตอนมีลูกค้าใหม่เข้ามา เราถามทั้ง 100 โมเดล
60 ตัวตอบ “ซื้อ” 40 ตัวตอบ “ไม่ซื้อ”
ก็เลือกซื้อ
เหตุผลคือโมเดลแต่ละตัวอาจผิดคนละแบบ เมื่อเอามาเฉลี่ยกัน ความผิดพลาดบางอย่างจะหักล้างกัน
เหมือนการถามความคิดเห็นหลายคนแทนที่จะเชื่อผู้เชี่ยวชาญคนเดียว
Bagging มีประโยชน์มากกับโมเดลที่ผลลัพธ์เปลี่ยนง่ายเมื่อข้อมูลเปลี่ยน เช่น Decision Tree
ภาพจำ: คณะกรรมการหลายคนดูข้อมูลคนละชุด แล้วโหวต
03How it works
ค่อยๆ ทำไปด้วยกัน ตั้งแต่ข้อมูลแถวแรกจนถึงการตรวจคำตอบ
เริ่มจากข้อมูลลูกค้าที่แบ่งชุดไว้แล้ว
เตรียม X เป็นพฤติกรรมก่อนตัดสินใจซื้อ y เป็นซื้อ/ไม่ซื้อ และกัน test ไว้ก่อนสร้างถุงข้อมูล ทุกถุงต้องสุ่มจาก train เท่านั้น หากสุ่มก่อนแล้วค่อยแยก test อาจมีลูกค้าคนเดียวกันหลุดไปอยู่ทั้งฝั่งฝึกและตรวจจนคะแนนดูดีเกินจริง
สร้างถุงที่มีคนซ้ำได้
สมมติ train มีรหัส A, B, C, D ถุงหนึ่งอาจได้ A, A, C, D อีกถุงได้ B, C, C, D นี่คือ bootstrap หรือการสุ่มแบบใส่คืน จำนวนแถวต่อถุงอาจเท่าเดิม แต่คนในถุงต่างกัน แล้วฝึกโมเดลฐานหนึ่งตัวต่อถุง เช่นต้นไม้หนึ่งต้นต่อถุง
รวมความคิดเห็นให้ตรงกับเครื่องมือ
ในภาพง่ายๆ คือโหวตคลาส แต่ BaggingClassifier เมื่อสมาชิกมี predict_proba จะเฉลี่ยความน่าจะเป็นของสมาชิกแล้วเลือกคลาสที่ได้สูงสุด ไม่จำเป็นต้องเหมือนการนับคำตอบแข็งๆ ของทุกต้น หากสมาชิกไม่มี probability จึงใช้การโหวต ส่วน BaggingRegressor เฉลี่ยค่าตัวเลข
เลือกจำนวนกรรมการกับข้อมูลที่ให้เห็น
เริ่ม BaggingClassifier(estimator=DecisionTreeClassifier(min_samples_leaf=3), n_estimators=100, max_samples=0.8, bootstrap=True, random_state=42) แล้ว fit(X_train, y_train) n_estimators คือจำนวนสมาชิก max_samples=0.8 คือแต่ละถุงใช้จำนวนแถว 80% ของ train และ estimator กำหนดนิสัยของโมเดลฐาน
ดูว่ารวมแล้วช่วยจริงหรือไม่
เทียบ predict(X_test) กับต้นไม้เดี่ยวด้วย confusion matrix และเวลาทำนาย ลองเพิ่มสมาชิกจาก 20 เป็น 100 โดยคงอย่างอื่นไว้ ถ้า bootstrap=True สามารถเปิด oob_score=True เพื่อดูคะแนนจากแถวที่สมาชิกนั้นไม่ได้ฝึกด้วยได้ แต่ยังควรมี test สุดท้าย Bagging ช่วยลดความผันผวนได้มากขึ้นเมื่อสมาชิกผิดต่างกัน ไม่ได้แก้ข้อมูลผิดหรือ feature ที่รั่วได้
ข้อมูล พารามิเตอร์ และภาพรวมการคำนวณ
n_estimatorsmax_samplesestimatorข้อมูลที่รับเข้ามา
รับ X และ y ตามชนิดของ base estimator จากนั้นสร้างชุดฝึกย่อยหลายชุดจากแถวหรือ feature ของข้อมูลเดิม
train = [A, B, C, D] → ถุงหนึ่ง [A, A, C, D]พารามิเตอร์ที่ใช้
- n_estimators
- จำนวนโมเดลสมาชิกที่ฝึกและนำมารวม
- max_samples
- จำนวนหรือสัดส่วนแถวต่อหนึ่งสมาชิก
- estimator
- ชนิดโมเดลฐาน เช่น Decision Tree
ผลลัพธ์ที่ได้
ได้คำทำนายรวมและสามารถดูผลของสมาชิกแต่ละตัวได้ ความผันผวนมักต่ำกว่าโมเดลเดี่ยว
BaggingClassifier + ต้นไม้ → เฉลี่ย probability แล้วเลือกคลาสคำนวณทีละขั้น
- 01
สุ่ม bootstrap sample ด้วยการหยิบแถวแล้วใส่คืนให้แต่ละสมาชิก
- 02
ฝึก base estimator แยกกันบนชุดสุ่ม ทำให้แต่ละตัวเรียนรู้กฎต่างกัน
- 03
BaggingClassifier เฉลี่ย probability เมื่อสมาชิกมี predict_proba มิฉะนั้นโหวตคลาส; Regressor เฉลี่ยค่าตัวเลข
ควรรู้อีกนิด — โมเดลที่มี bias สูงจะไม่ได้ดีขึ้นมาก และจำนวนโมเดลเพิ่มต้นทุนคำนวณ
04Make it yours
# ติดตั้ง: pip install numpy scikit-learn matplotlibfrom sklearn.ensemble import BaggingClassifierfrom sklearn.metrics import accuracy_score from sklearn.datasets import make_classificationfrom sklearn.model_selection import train_test_split X, y = make_classification( n_samples=150, n_features=2, n_redundant=0, n_informative=2, n_classes=3, n_clusters_per_class=1, class_sep=1.4, random_state=42,)X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y) model = BaggingClassifier(n_estimators=11, random_state=42)model.fit(X_train, y_train)pred = model.predict(X_test)print("Accuracy:", accuracy_score(y_test, pred))โค้ดเปลี่ยนตามค่าที่เลือกใน Playground · แต่ละภาษาใช้ข้อมูลตัวอย่างตามที่ระบุในโค้ด
05Learn by playing
ปรับ จำนวน estimators แล้วสังเกตรูปแบบคำทำนายและตัวชี้วัดที่คำนวณใหม่ทันที
Playground เป็น implementation เพื่อการเรียนรู้ที่คำนวณในเบราว์เซอร์ ส่วนโค้ด Python ใช้ scikit-learn จึงอาจให้ค่าต่างกันเล็กน้อยจากรายละเอียดการ optimize และค่าเริ่มต้นของไลบรารี ผลนี้ไม่ใช่ benchmark บนข้อมูลจริง