01Overall Concept
ไอเดียหลัก — Linear Discriminant Analysis หรือ LDA หามุมมองที่ทำให้กลุ่มต่าง ๆ แยกจากกันชัดที่สุด จากข้อมูลที่มีหลายมิติ โมเดลจะย่อให้เหลือแนวสำคัญแล้วสร้างเส้นแบ่งระหว่างกลุ่ม
ลองนึกภาพว่า — ลองส่องไฟไปที่ลูกแก้วหลายสีบนโต๊ะ ถ้าส่องผิดมุม เงาของทุกสีอาจทับกัน แต่ถ้าหมุนไฟจนได้มุมดี เงาของแต่ละสีจะแยกออกจากกันและแบ่งกลุ่มได้ง่าย
ตัวอย่างการนำไปใช้ — จำแนกชนิดดอกไม้ แยกกลุ่มลูกค้าจากตัวเลขหลายค่า หรือย่อมิติข้อมูลก่อนนำไปดูและวิเคราะห์ต่อ
02อธิบายภาษาคนเข้าใจง่ายๆ
LDA พยายามหามุมมองที่ทำให้กลุ่มต่างๆ แยกออกจากกันให้ชัดที่สุด
สมมติเรามีผลไม้สองชนิด
แอปเปิลกับส้ม
ข้อมูลแต่ละลูกมี
น้ำหนัก ความหวาน สี ขนาด
ถ้าเราเอาทุกอย่างมาดูพร้อมกันอาจวุ่นวาย
LDA จะพยายามหาการผสมตัวแปรที่ทำให้สองกลุ่มนี้แยกกันได้ดีที่สุด
เช่นอาจพบว่า
“ถ้าเอาความหวาน × น้ำหนัก × สี มารวมแบบนี้ จะเห็นเส้นแบ่งแอปเปิลกับส้มชัดมาก”
จุดแข็งของ LDA คือทั้ง Classification และช่วยลดจำนวนมิติของข้อมูลได้
แต่มีสมมติฐานบางอย่างเกี่ยวกับรูปแบบการกระจายของข้อมูล ดังนั้นถ้าข้อมูลแต่ละกลุ่มมีรูปร่างต่างกันมาก มันอาจทำงานไม่ดี
ภาพจำ: หมุนกล้องไปหามุมที่ทำให้คนสองกลุ่มยืนแยกกันชัดที่สุด
03How it works
ค่อยๆ ทำไปด้วยกัน ตั้งแต่ข้อมูลแถวแรกจนถึงการตรวจคำตอบ
เริ่มจากแอปเปิลกับส้มที่มีป้ายชื่อ
เตรียม X เป็นน้ำหนัก ความหวาน และขนาดที่วัดเป็นตัวเลข ส่วน y เป็นชื่อผลไม้ ไม่ใช่รหัสประจำลูก แบ่งชุดฝึกและทดสอบโดยรักษาสัดส่วนคลาส และจัดการค่าที่ขาดก่อน ต้องมีหลายตัวอย่างในแต่ละชนิดให้โมเดลเห็นการกระจายจริง
หาจุดกลางและรูปร่างร่วม
ตอน fit LDA หาเวกเตอร์ค่าเฉลี่ยของแต่ละคลาส เช่นแอปเปิลกลางๆ หนักและหวานเท่าไร จากนั้นประมาณ covariance ร่วม ซึ่งบอกว่าคอลัมน์ต่างๆ กระจายและเปลี่ยนไปด้วยกันอย่างไร ทุกคลาสใช้รูปร่างการกระจายเดียวกัน แต่มีจุดกลางคนละจุด นี่คือข้อสมมติหลักที่ทำให้เส้นแบ่งเป็นเส้นตรง
ผลไม้ใหม่ได้คะแนนอย่างไร
โมเดลดูว่าค่าของผลไม้ใหม่เข้ากับการกระจายของแต่ละคลาสแค่ไหน รวมกับ prior หรือสัดส่วนโอกาสของคลาส แล้วเลือกคะแนนสูงสุด จึงไม่ได้คูณน้ำหนัก × ความหวาน × สีตรงๆ ภาพ “หมุนกล้อง” ในตอนก่อนเป็นอีกมุมหนึ่งของการหาแกนที่แยกคลาสได้ดี
เลือกว่าจะจำแนกหรือย่อมิติ
ถ้าต้องการจำแนกอย่างเดียว เริ่ม LinearDiscriminantAnalysis(solver='lsqr', shrinkage='auto') แล้ว fit และ predict ได้ shrinkage ช่วยให้ covariance เสถียรขึ้น หากต้องการ transform เพื่อวาดข้อมูลบนแกนใหม่ ให้ใช้ solver='svd' หรือ 'eigen' แทน เพราะ lsqr ไม่รองรับ transform และ svd ไม่รองรับ shrinkage
ดูผลให้ตรงงานที่ใช้
predict_proba ให้โอกาสแต่ละคลาส ส่วน n_components ใช้เลือกจำนวนแกนตอนลดมิติ สูงสุดคือค่าน้อยกว่าระหว่างจำนวน feature กับจำนวนคลาสลบหนึ่ง ดังนั้นสองชนิดย่อได้สูงสุดหนึ่งแกน ตรวจ confusion matrix บน test และเทียบ QDA หากกลุ่มมีรูปร่างต่างกันชัดเจน โดยใช้ข้อมูลแบ่งชุดเดิมเพื่อเทียบอย่างยุติธรรม
ข้อมูล พารามิเตอร์ และภาพรวมการคำนวณ
solvershrinkagen_componentsข้อมูลที่รับเข้ามา
รับ X เป็นตารางตัวเลขและ y เป็นคลาส ต้องมีตัวอย่างหลายแถวในแต่ละคลาสเพื่อประมาณค่าเฉลี่ยและ covariance ร่วม
X = [น้ำหนัก, ความหวาน, ขนาด] · y = แอปเปิล / ส้มพารามิเตอร์ที่ใช้
- solver
- lsqr ใช้จำแนกได้แต่ไม่มี transform; svd/eigen ใช้ลดมิติได้
- shrinkage
- ใช้กับ lsqr/eigen เท่านั้น ลอง 'auto' เพื่อช่วยให้ covariance เสถียร
- n_components
- จำนวนแกนตอน transform ไม่เกิน min(จำนวน feature, จำนวนคลาส − 1)
ผลลัพธ์ที่ได้
predict ให้คลาส predict_proba ให้โอกาส; transform ให้แกนใหม่เฉพาะ solver ที่รองรับ
สองคลาส → transform ลดได้สูงสุด 1 แกน เมื่อ solver รองรับคำนวณทีละขั้น
- 01
หา mean ต่อคลาส และ covariance ที่ใช้ร่วมกัน พร้อม prior ของแต่ละคลาส
- 02
คำนวณ discriminant score ของข้อมูลใหม่จาก mean, covariance และ prior
- 03
เลือกคลาสคะแนนสูงสุด; ถ้าต้องการลดมิติ ใช้ transform กับ solver ที่รองรับ
ควรรู้อีกนิด — สมมติแต่ละคลาสมี covariance เดียวกันและขอบเขตจึงเป็นเส้นตรง
04Make it yours
# ติดตั้ง: pip install numpy scikit-learn matplotlibfrom sklearn.discriminant_analysis import LinearDiscriminantAnalysisfrom 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 = LinearDiscriminantAnalysis(solver="lsqr", shrinkage=0.20)model.fit(X_train, y_train)pred = model.predict(X_test)print("Accuracy:", accuracy_score(y_test, pred))โค้ดเปลี่ยนตามค่าที่เลือกใน Playground · แต่ละภาษาใช้ข้อมูลตัวอย่างตามที่ระบุในโค้ด
05Learn by playing
ปรับ shrinkage แล้วสังเกตรูปแบบคำทำนายและตัวชี้วัดที่คำนวณใหม่ทันที
Playground เป็น implementation เพื่อการเรียนรู้ที่คำนวณในเบราว์เซอร์ ส่วนโค้ด Python ใช้ scikit-learn จึงอาจให้ค่าต่างกันเล็กน้อยจากรายละเอียดการ optimize และค่าเริ่มต้นของไลบรารี ผลนี้ไม่ใช่ benchmark บนข้อมูลจริง