ml/ library Learn by doing
ALGORITHM 50 · PYTHON / JAVASCRIPT

Quadratic Discriminant Analysis

ให้แต่ละคลาสมีรูปทรงของตัวเอง

LEARNING LEVEL3
ผสานหลายแนวคิดควรรู้มาก่อน · Linear Discriminant Analysis
ลองใน Playground

01Overall Concept

OVERALL CONCEPT

ไอเดียหลัก — Quadratic Discriminant Analysis หรือ QDA คล้าย LDA แต่ยอมให้แต่ละกลุ่มมีรูปร่างและการกระจายของตัวเอง ขอบเขตจึงโค้งได้ และเหมาะกับกลุ่มที่ไม่ได้กางออกไปในทิศเดียวกัน

ลองนึกภาพว่า — ถ้าเด็กแต่ละห้องยืนเป็นกลุ่มบนสนาม บางห้องอาจยืนเป็นวงกลม บางห้องเป็นวงรียาว QDA วาดรั้วให้เข้ากับรูปร่างของแต่ละห้อง แทนการใช้ไม้บรรทัดเส้นเดียวแบ่งทุกห้อง

ตัวอย่างการนำไปใช้ — จำแนกชนิดสิ่งมีชีวิตจากการวัดหลายค่า แยกสัญญาณเซนเซอร์ หรือจำแนกกลุ่มที่มีความกระจายต่างกันอย่างชัดเจน

02อธิบายภาษาคนเข้าใจง่ายๆ

เล่าแบบไม่ใช้ศัพท์ยาก

QDA คือญาติที่ยืดหยุ่นกว่าของ LDA

LDA พยายามแบ่งกลุ่มด้วยขอบเขตค่อนข้างตรง

แต่ QDA บอกว่า

“แต่ถ้ากลุ่มมันมีรูปร่างต่างกันล่ะ?”

สมมติกลุ่ม A กระจายเป็นวงรีแนวนอน ส่วนกลุ่ม B กระจายเป็นวงกลม

LDA อาจลากเส้นตรงแบ่งไม่สวย

QDA สามารถสร้างเส้นขอบที่โค้งได้ จึงจับรูปแบบที่ซับซ้อนกว่า

แต่ความยืดหยุ่นก็มีราคา เพราะ QDA ต้องเรียนรู้รายละเอียดเยอะกว่า จึงต้องการข้อมูลมากกว่า และถ้าข้อมูลน้อยอาจ Overfit ได้ง่าย

ภาพจำ: LDA ใช้ไม้บรรทัดแบ่งพื้นที่ ส่วน QDA ใช้เชือกที่ดัดตามรูปร่างของข้อมูลได้

03How it works

ค่อยๆ ทำไปด้วยกัน ตั้งแต่ข้อมูลแถวแรกจนถึงการตรวจคำตอบ

  1. ใช้ตารางเดิม แต่ยอมให้กลุ่มรูปร่างต่างกัน

    เตรียม X เป็นน้ำหนัก ความหวาน และขนาดผลไม้ ส่วน y คือชนิด แบ่ง train/test แบบ stratify=y เช่นเดียวกับ LDA คราวนี้ต้องสนใจจำนวนแถวต่อคลาสเป็นพิเศษ เพราะเราจะให้แต่ละกลุ่มมีรายละเอียดการกระจายของตัวเอง

  2. แต่ละคลาสมีแผนที่ของตัวเอง

    ตอน fit QDA หา mean และ covariance แยกแต่ละคลาส กลุ่มหนึ่งจึงยาวตามแกนน้ำหนักได้ ขณะที่อีกกลุ่มกระจายเกือบกลม covariance บอกทั้งความกว้างและความเอียง ไม่ใช่แค่ขนาดวงกลมรอบค่าเฉลี่ย ความอิสระนี้ทำให้ต้องประมาณค่ามากกว่า LDA

  3. คำนวณว่าจุดใหม่เข้ากับแผนที่ไหน

    สำหรับแต่ละคลาส โมเดลดูระยะจากจุดกลางโดยคำนึงถึง covariance รวมกับขนาดการกระจายและ prior แล้วเทียบคะแนนความเป็นไปได้ ไม่ใช่เลือกจุดกลางที่ใกล้ด้วยไม้บรรทัดธรรมดา ขอบเขตที่คะแนนสองฝั่งเท่ากันจึงโค้งได้

  4. เริ่มฝึกแล้วคุมความยืดหยุ่น

    เริ่ม QuadraticDiscriminantAnalysis(reg_param=0.1) แล้ว fit(X_train, y_train) ค่า reg_param อยู่ระหว่าง 0 กับ 1 และช่วยดึงค่าการกระจายเข้าหารูปแบบที่เสถียรกว่า ก่อนปรับค่านี้ควรจัดสเกลให้เหมาะเพราะมีผลต่อ regularization หากมีคำเตือน covariance ไม่เต็มอันดับ ให้ตรวจคอลัมน์ซ้ำ ลด feature หรือเพิ่มข้อมูลต่อคลาส

  5. ตรวจว่าความโค้งคุ้มจริงหรือไม่

    predict(X_test) ให้คลาสและ predict_proba ให้คะแนนเปรียบเทียบ ลอง reg_param หลายค่าใน validation แล้วดู confusion matrix บน test เทียบกับ LDA ถ้าฝึกดีมากแต่ทดสอบแย่ ความยืดหยุ่นอาจเกินจำนวนข้อมูลที่มี ควรลดความซับซ้อน แทนการเลือก QDA เพียงเพราะเส้นแบ่งดูสวยกว่า

เปิดตัวอย่างโค้ดเพื่อลองทำตาม →ตัวอย่างตัวเลขในเรื่องใช้ช่วยอธิบาย ส่วนโค้ดและ Playground ใช้ชุดข้อมูลสาธิตของแต่ละหน้าอ่านเอกสารอ้างอิงของเทคนิคนี้ ↗

ข้อมูล พารามิเตอร์ และภาพรวมการคำนวณ

DATA INX · featuresy · targetX = [น้ำหนัก, ความหวาน, ขนาด] · y = แอปเปิล / ส้ม
CALCULATEQuadratic Discriminant Analysis
reg_parampriorstol
RESULT0.800.150.05class / probabilitymean และ covariance แยกคลาส → เส้นแบ่งโค้งได้
เส้นทางของข้อมูล: จากค่าที่รับเข้า ผ่านการคำนวณด้วยพารามิเตอร์ ไปเป็นผลลัพธ์
INPUT

ข้อมูลที่รับเข้ามา

รับ X เป็นตารางตัวเลขและ y เป็นคลาสเหมือน LDA แต่ต้องมีข้อมูลต่อคลาสมากพอสำหรับ covariance ของตัวเอง

X = [น้ำหนัก, ความหวาน, ขนาด] · y = แอปเปิล / ส้ม
PARAMETERS

พารามิเตอร์ที่ใช้

reg_param
ผสม covariance กับค่าที่เรียบขึ้นเพื่อกันเมทริกซ์ไม่นิ่ง
priors
โอกาสเริ่มต้นของแต่ละคลาส
tol
ค่าต่ำสุดที่ใช้แจ้งเตือนว่า covariance ใกล้เอกฐาน
OUTPUT

ผลลัพธ์ที่ได้

ได้ความน่าจะเป็นและป้ายคลาส โดยขอบเขตระหว่างคลาสสามารถเป็นเส้นโค้ง

mean และ covariance แยกคลาส → เส้นแบ่งโค้งได้
CALCULATION

คำนวณทีละขั้น

  1. 01

    คำนวณ mean vector และ covariance matrix แยกกันสำหรับทุกคลาส

  2. 02

    วัดว่าจุดใหม่เข้ากับศูนย์กลางและรูปทรงการกระจายของแต่ละคลาสเพียงใด

  3. 03

    รวมระยะเชิง covariance, ขนาดการกระจาย และ prior เป็นคะแนน quadratic แล้วเลือกค่าสูงสุด

ควรรู้อีกนิด — ใช้พารามิเตอร์มากกว่า LDA จึง overfit ง่ายเมื่อข้อมูลน้อยหรือมิติสูง

04Make it yours

Python · scikit-learn
# ติดตั้ง: 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 แล้วสังเกตรูปแบบคำทำนายและตัวชี้วัดที่คำนวณใหม่ทันที

Sample dataset / Three classes● คำนวณใหม่เมื่อปรับค่า
เพิ่ม regularization ให้ covariance ของแต่ละคลาส
พื้นที่สีคือคำทำนาย จุดคือคำตอบจริงFeature x → · Feature y ↑ · ขอบเข้ม = ชุดทดสอบ
Test accuracy93.3%
ชุดทดสอบ30 จุด
พารามิเตอร์ที่ลอง0.10

Playground เป็น implementation เพื่อการเรียนรู้ที่คำนวณในเบราว์เซอร์ ส่วนโค้ด Python ใช้ scikit-learn จึงอาจให้ค่าต่างกันเล็กน้อยจากรายละเอียดการ optimize และค่าเริ่มต้นของไลบรารี ผลนี้ไม่ใช่ benchmark บนข้อมูลจริง