01Overall Concept
ไอเดียหลัก — Quadratic Discriminant Analysis หรือ QDA คล้าย LDA แต่ยอมให้แต่ละกลุ่มมีรูปร่างและการกระจายของตัวเอง ขอบเขตจึงโค้งได้ และเหมาะกับกลุ่มที่ไม่ได้กางออกไปในทิศเดียวกัน
ลองนึกภาพว่า — ถ้าเด็กแต่ละห้องยืนเป็นกลุ่มบนสนาม บางห้องอาจยืนเป็นวงกลม บางห้องเป็นวงรียาว QDA วาดรั้วให้เข้ากับรูปร่างของแต่ละห้อง แทนการใช้ไม้บรรทัดเส้นเดียวแบ่งทุกห้อง
ตัวอย่างการนำไปใช้ — จำแนกชนิดสิ่งมีชีวิตจากการวัดหลายค่า แยกสัญญาณเซนเซอร์ หรือจำแนกกลุ่มที่มีความกระจายต่างกันอย่างชัดเจน
02อธิบายภาษาคนเข้าใจง่ายๆ
QDA คือญาติที่ยืดหยุ่นกว่าของ LDA
LDA พยายามแบ่งกลุ่มด้วยขอบเขตค่อนข้างตรง
แต่ QDA บอกว่า
“แต่ถ้ากลุ่มมันมีรูปร่างต่างกันล่ะ?”
สมมติกลุ่ม A กระจายเป็นวงรีแนวนอน ส่วนกลุ่ม B กระจายเป็นวงกลม
LDA อาจลากเส้นตรงแบ่งไม่สวย
QDA สามารถสร้างเส้นขอบที่โค้งได้ จึงจับรูปแบบที่ซับซ้อนกว่า
แต่ความยืดหยุ่นก็มีราคา เพราะ QDA ต้องเรียนรู้รายละเอียดเยอะกว่า จึงต้องการข้อมูลมากกว่า และถ้าข้อมูลน้อยอาจ Overfit ได้ง่าย
ภาพจำ: LDA ใช้ไม้บรรทัดแบ่งพื้นที่ ส่วน QDA ใช้เชือกที่ดัดตามรูปร่างของข้อมูลได้
03How it works
ค่อยๆ ทำไปด้วยกัน ตั้งแต่ข้อมูลแถวแรกจนถึงการตรวจคำตอบ
ใช้ตารางเดิม แต่ยอมให้กลุ่มรูปร่างต่างกัน
เตรียม X เป็นน้ำหนัก ความหวาน และขนาดผลไม้ ส่วน y คือชนิด แบ่ง train/test แบบ stratify=y เช่นเดียวกับ LDA คราวนี้ต้องสนใจจำนวนแถวต่อคลาสเป็นพิเศษ เพราะเราจะให้แต่ละกลุ่มมีรายละเอียดการกระจายของตัวเอง
แต่ละคลาสมีแผนที่ของตัวเอง
ตอน fit QDA หา mean และ covariance แยกแต่ละคลาส กลุ่มหนึ่งจึงยาวตามแกนน้ำหนักได้ ขณะที่อีกกลุ่มกระจายเกือบกลม covariance บอกทั้งความกว้างและความเอียง ไม่ใช่แค่ขนาดวงกลมรอบค่าเฉลี่ย ความอิสระนี้ทำให้ต้องประมาณค่ามากกว่า LDA
คำนวณว่าจุดใหม่เข้ากับแผนที่ไหน
สำหรับแต่ละคลาส โมเดลดูระยะจากจุดกลางโดยคำนึงถึง covariance รวมกับขนาดการกระจายและ prior แล้วเทียบคะแนนความเป็นไปได้ ไม่ใช่เลือกจุดกลางที่ใกล้ด้วยไม้บรรทัดธรรมดา ขอบเขตที่คะแนนสองฝั่งเท่ากันจึงโค้งได้
เริ่มฝึกแล้วคุมความยืดหยุ่น
เริ่ม QuadraticDiscriminantAnalysis(reg_param=0.1) แล้ว fit(X_train, y_train) ค่า reg_param อยู่ระหว่าง 0 กับ 1 และช่วยดึงค่าการกระจายเข้าหารูปแบบที่เสถียรกว่า ก่อนปรับค่านี้ควรจัดสเกลให้เหมาะเพราะมีผลต่อ regularization หากมีคำเตือน covariance ไม่เต็มอันดับ ให้ตรวจคอลัมน์ซ้ำ ลด feature หรือเพิ่มข้อมูลต่อคลาส
ตรวจว่าความโค้งคุ้มจริงหรือไม่
predict(X_test) ให้คลาสและ predict_proba ให้คะแนนเปรียบเทียบ ลอง reg_param หลายค่าใน validation แล้วดู confusion matrix บน test เทียบกับ LDA ถ้าฝึกดีมากแต่ทดสอบแย่ ความยืดหยุ่นอาจเกินจำนวนข้อมูลที่มี ควรลดความซับซ้อน แทนการเลือก QDA เพียงเพราะเส้นแบ่งดูสวยกว่า
ข้อมูล พารามิเตอร์ และภาพรวมการคำนวณ
reg_parampriorstolข้อมูลที่รับเข้ามา
รับ X เป็นตารางตัวเลขและ y เป็นคลาสเหมือน LDA แต่ต้องมีข้อมูลต่อคลาสมากพอสำหรับ covariance ของตัวเอง
X = [น้ำหนัก, ความหวาน, ขนาด] · y = แอปเปิล / ส้มพารามิเตอร์ที่ใช้
- reg_param
- ผสม covariance กับค่าที่เรียบขึ้นเพื่อกันเมทริกซ์ไม่นิ่ง
- priors
- โอกาสเริ่มต้นของแต่ละคลาส
- tol
- ค่าต่ำสุดที่ใช้แจ้งเตือนว่า covariance ใกล้เอกฐาน
ผลลัพธ์ที่ได้
ได้ความน่าจะเป็นและป้ายคลาส โดยขอบเขตระหว่างคลาสสามารถเป็นเส้นโค้ง
mean และ covariance แยกคลาส → เส้นแบ่งโค้งได้คำนวณทีละขั้น
- 01
คำนวณ mean vector และ covariance matrix แยกกันสำหรับทุกคลาส
- 02
วัดว่าจุดใหม่เข้ากับศูนย์กลางและรูปทรงการกระจายของแต่ละคลาสเพียงใด
- 03
รวมระยะเชิง covariance, ขนาดการกระจาย และ prior เป็นคะแนน quadratic แล้วเลือกค่าสูงสุด
ควรรู้อีกนิด — ใช้พารามิเตอร์มากกว่า LDA จึง overfit ง่ายเมื่อข้อมูลน้อยหรือมิติสูง
04Make it yours
# ติดตั้ง: pip install numpy scikit-learn matplotlibfrom sklearn.discriminant_analysis import QuadraticDiscriminantAnalysisfrom 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 = QuadraticDiscriminantAnalysis(reg_param=0.10)model.fit(X_train, y_train)pred = model.predict(X_test)print("Accuracy:", accuracy_score(y_test, pred))โค้ดเปลี่ยนตามค่าที่เลือกใน Playground · แต่ละภาษาใช้ข้อมูลตัวอย่างตามที่ระบุในโค้ด
05Learn by playing
ปรับ reg_param แล้วสังเกตรูปแบบคำทำนายและตัวชี้วัดที่คำนวณใหม่ทันที
Playground เป็น implementation เพื่อการเรียนรู้ที่คำนวณในเบราว์เซอร์ ส่วนโค้ด Python ใช้ scikit-learn จึงอาจให้ค่าต่างกันเล็กน้อยจากรายละเอียดการ optimize และค่าเริ่มต้นของไลบรารี ผลนี้ไม่ใช่ benchmark บนข้อมูลจริง