01Overall Concept
ไอเดียหลัก — Support Vector Machine หรือ SVM มองหาเส้นแบ่งที่เว้นทางว่างระหว่างสองกลุ่มให้กว้างที่สุด โมเดลสนใจจุดที่อยู่ใกล้เส้นแบ่งเป็นพิเศษ เพราะจุดเหล่านี้เป็นตัวกำหนดว่าเส้นควรวางตรงไหน
ลองนึกภาพว่า — ลองวางถนนคั่นระหว่างหมู่บ้านสีเขียวกับสีม่วง เราอยากให้ถนนกว้างและไม่ชนบ้าน บ้านที่อยู่ริมถนนที่สุดคือ support vectors ซึ่งคอยกำหนดแนวและความกว้างของถนน
ตัวอย่างการนำไปใช้ — แยกหมวดเอกสาร จำแนกภาพจาก feature จำนวนมาก หรือแก้โจทย์ที่มีข้อมูลไม่มหาศาลแต่ต้องการขอบเขตชัดเจน
02อธิบายภาษาคนเข้าใจง่ายๆ
SVM ไม่ได้คิดแค่ว่า
“ขอเส้นอะไรก็ได้ที่แบ่งสองกลุ่มออกจากกัน”
แต่มันถามว่า
“มีเส้นไหนที่แบ่งแล้วปลอดภัยที่สุด?”
สมมติมีคนใส่เสื้อแดงยืนทางซ้าย และเสื้อน้ำเงินอยู่ทางขวา
เราจะสร้างรั้วตรงกลาง
SVM ไม่สร้างรั้วชิดฝั่งแดงหรือชิดฝั่งน้ำเงิน แต่พยายามสร้างตรงจุดที่มี ช่องว่างจากสองฝ่ายมากที่สุด
ช่องว่างนี้เรียกว่า Margin
เหตุผลคือ ถ้าข้อมูลใหม่เข้ามาแล้วตำแหน่งคลาดเคลื่อนเล็กน้อย เรายังมีพื้นที่กันชนอยู่
สิ่งที่น่าสนใจมากของ SVM คือมันสามารถใช้สิ่งที่เรียกว่า Kernel เพื่อจัดการข้อมูลที่แบ่งด้วยเส้นตรงไม่ได้
ลองนึกภาพจุดสีแดงอยู่ตรงกลาง และสีน้ำเงินล้อมรอบเป็นวง
บนกระดาษ 2D เราลากเส้นตรงแบ่งไม่ได้
Kernel เหมือนยกข้อมูลจากกระดาษขึ้นมาเป็นภูเขาใน 3D แล้วจู่ๆ เราสามารถใช้แผ่นระนาบแบ่งได้
นี่คือเหตุผลที่ SVM เคยดังมากในงาน Machine Learning ก่อนยุค Deep Learning
ภาพจำ: สร้างรั้วที่มีพื้นที่กันชนกว้างที่สุด
03How it works
ค่อยๆ ทำไปด้วยกัน ตั้งแต่ข้อมูลแถวแรกจนถึงการตรวจคำตอบ
เริ่มจากคนเสื้อสองสีในรูปตาราง
ให้ X เป็น feature ตัวเลขของแต่ละตัวอย่าง และ y เป็นคลาส เช่นซื้อ/ไม่ซื้อ แบ่ง train/test และปรับสเกลด้วย StandardScaler ภายใน Pipeline ก่อน SVM ใช้ระยะและตำแหน่งของข้อมูล สเกลจึงมีผลกับรั้วที่มันจะสร้างโดยตรง
หารั้วพร้อมพื้นที่กันชน
สำหรับ kernel='linear' โมเดลหาน้ำหนักของเส้นแบ่งที่ทำให้ margin กว้าง พร้อมยอมให้บางจุดเข้ามาในพื้นที่กันชนหรืออยู่ผิดฝั่งเมื่อจำเป็น จุดฝึกที่มีอิทธิพลต่อคำตอบเรียกว่า support vectors จึงไม่ใช่เส้นที่แค่แบ่งข้อมูลฝึกถูกให้มากที่สุดอย่างเดียว
เลือกว่าจะยอมผิดมากน้อยแค่ไหน
ค่า C คุมราคาของการละเมิด margin เมื่อ C สูง โมเดลพยายามหลีกเลี่ยงการละเมิดมากขึ้น เมื่อ C ต่ำจะยอมประนีประนอมได้มาก เริ่ม make_pipeline(StandardScaler(), SVC(C=1.0, kernel='linear')) แล้ว fit(X_train, y_train) จากนั้นลอง C=0.1, 1, 10 บน validation
ถ้ารั้วตรงยังแบ่งไม่ได้
ลอง kernel='rbf' และ gamma='scale' โดย gamma คุมว่าจุดหนึ่งส่งผลในบริเวณกว้างแค่ไหน gamma สูงมักทำให้ขอบเขตละเอียดมากขึ้น ส่วน gamma ต่ำมักเรียบขึ้น ตัว kernel คำนวณความคล้ายเสมือนทำงานในพื้นที่ใหม่ โดยเราไม่จำเป็นต้องสร้างภูเขา 3 มิติขึ้นมาจริงๆ และ gamma ไม่มีผลกับ linear kernel
อ่านคำตอบและเลือกความซับซ้อน
predict ให้คลาส ส่วน decision_function ให้คะแนนฝั่งของรั้วซึ่งไม่ใช่ probability ถ้าต้องการ predict_proba ต้องตั้ง probability=True ก่อน fit และจะฝึกเพิ่มเพื่อประมาณความน่าจะเป็น ตรวจ precision/recall บน test และเลือก C กับ gamma จาก validation หากขอบเขตโค้งเล็กๆ ตามทุกจุดฝึกแต่ทดสอบแย่ ให้ลดความซับซ้อน
ข้อมูล พารามิเตอร์ และภาพรวมการคำนวณ
Ckernelgammaข้อมูลที่รับเข้ามา
รับ X เป็นตารางตัวเลขที่ควรปรับสเกล และ y เป็นป้ายคลาสหรือค่าต่อเนื่อง เหมาะกับ feature จำนวนมากและข้อมูลขนาดกลาง
X = feature ตัวเลขที่ปรับสเกล · y = ซื้อ / ไม่ซื้อพารามิเตอร์ที่ใช้
- C
- ค่าปรับจุดผิดฝั่ง; สูงเน้นข้อมูลฝึก ต่ำเน้น margin
- kernel
- วิธีวัดความคล้าย เช่น linear, polynomial หรือ RBF
- gamma
- ระยะอิทธิพลของแต่ละจุดเมื่อใช้ RBF kernel
ผลลัพธ์ที่ได้
ได้ป้ายคลาสและ decision score; probability มีได้เมื่อเปิด probability=True และคำนวณเพิ่ม
decision_function → คะแนนฝั่งรั้ว · predict → คลาสคำนวณทีละขั้น
- 01
คำนวณตำแหน่งของจุดใน feature space หรือ kernel space
- 02
หา hyperplane ที่ทำให้ margin ถึงจุดใกล้ขอบกว้างที่สุด พร้อมค่าปรับจากจุดผิดฝั่ง
- 03
เก็บ support vectors ที่กำหนดขอบเขต แล้วใช้ระยะมีเครื่องหมายจากขอบเขตเป็นคะแนนทำนาย
ควรรู้อีกนิด — ต้องปรับสเกล feature และ kernel SVM อาจช้ามากเมื่อจำนวนข้อมูลสูง
04Make it yours
# ติดตั้ง: pip install numpy scikit-learn matplotlibfrom sklearn.svm import SVCfrom 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 = SVC(C=1.0, kernel="linear", probability=True, 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
ปรับ C แล้วสังเกตรูปแบบคำทำนายและตัวชี้วัดที่คำนวณใหม่ทันที
Playground เป็น implementation เพื่อการเรียนรู้ที่คำนวณในเบราว์เซอร์ ส่วนโค้ด Python ใช้ scikit-learn จึงอาจให้ค่าต่างกันเล็กน้อยจากรายละเอียดการ optimize และค่าเริ่มต้นของไลบรารี ผลนี้ไม่ใช่ benchmark บนข้อมูลจริง