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

Linear Discriminant Analysis

หาแนวฉายที่แยกคลาสได้ชัดที่สุด

LEARNING LEVEL2
ต่อยอดโดยตรงควรรู้มาก่อน · Naive Bayes, distribution และ covariance
ลองใน Playground

01Overall Concept

OVERALL CONCEPT

ไอเดียหลัก — Linear Discriminant Analysis หรือ LDA หามุมมองที่ทำให้กลุ่มต่าง ๆ แยกจากกันชัดที่สุด จากข้อมูลที่มีหลายมิติ โมเดลจะย่อให้เหลือแนวสำคัญแล้วสร้างเส้นแบ่งระหว่างกลุ่ม

ลองนึกภาพว่า — ลองส่องไฟไปที่ลูกแก้วหลายสีบนโต๊ะ ถ้าส่องผิดมุม เงาของทุกสีอาจทับกัน แต่ถ้าหมุนไฟจนได้มุมดี เงาของแต่ละสีจะแยกออกจากกันและแบ่งกลุ่มได้ง่าย

ตัวอย่างการนำไปใช้ — จำแนกชนิดดอกไม้ แยกกลุ่มลูกค้าจากตัวเลขหลายค่า หรือย่อมิติข้อมูลก่อนนำไปดูและวิเคราะห์ต่อ

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

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

LDA พยายามหามุมมองที่ทำให้กลุ่มต่างๆ แยกออกจากกันให้ชัดที่สุด

สมมติเรามีผลไม้สองชนิด

แอปเปิลกับส้ม

ข้อมูลแต่ละลูกมี

น้ำหนัก ความหวาน สี ขนาด

ถ้าเราเอาทุกอย่างมาดูพร้อมกันอาจวุ่นวาย

LDA จะพยายามหาการผสมตัวแปรที่ทำให้สองกลุ่มนี้แยกกันได้ดีที่สุด

เช่นอาจพบว่า

“ถ้าเอาความหวาน × น้ำหนัก × สี มารวมแบบนี้ จะเห็นเส้นแบ่งแอปเปิลกับส้มชัดมาก”

จุดแข็งของ LDA คือทั้ง Classification และช่วยลดจำนวนมิติของข้อมูลได้

แต่มีสมมติฐานบางอย่างเกี่ยวกับรูปแบบการกระจายของข้อมูล ดังนั้นถ้าข้อมูลแต่ละกลุ่มมีรูปร่างต่างกันมาก มันอาจทำงานไม่ดี

ภาพจำ: หมุนกล้องไปหามุมที่ทำให้คนสองกลุ่มยืนแยกกันชัดที่สุด

03How it works

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

  1. เริ่มจากแอปเปิลกับส้มที่มีป้ายชื่อ

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

  2. หาจุดกลางและรูปร่างร่วม

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

  3. ผลไม้ใหม่ได้คะแนนอย่างไร

    โมเดลดูว่าค่าของผลไม้ใหม่เข้ากับการกระจายของแต่ละคลาสแค่ไหน รวมกับ prior หรือสัดส่วนโอกาสของคลาส แล้วเลือกคะแนนสูงสุด จึงไม่ได้คูณน้ำหนัก × ความหวาน × สีตรงๆ ภาพ “หมุนกล้อง” ในตอนก่อนเป็นอีกมุมหนึ่งของการหาแกนที่แยกคลาสได้ดี

  4. เลือกว่าจะจำแนกหรือย่อมิติ

    ถ้าต้องการจำแนกอย่างเดียว เริ่ม LinearDiscriminantAnalysis(solver='lsqr', shrinkage='auto') แล้ว fit และ predict ได้ shrinkage ช่วยให้ covariance เสถียรขึ้น หากต้องการ transform เพื่อวาดข้อมูลบนแกนใหม่ ให้ใช้ solver='svd' หรือ 'eigen' แทน เพราะ lsqr ไม่รองรับ transform และ svd ไม่รองรับ shrinkage

  5. ดูผลให้ตรงงานที่ใช้

    predict_proba ให้โอกาสแต่ละคลาส ส่วน n_components ใช้เลือกจำนวนแกนตอนลดมิติ สูงสุดคือค่าน้อยกว่าระหว่างจำนวน feature กับจำนวนคลาสลบหนึ่ง ดังนั้นสองชนิดย่อได้สูงสุดหนึ่งแกน ตรวจ confusion matrix บน test และเทียบ QDA หากกลุ่มมีรูปร่างต่างกันชัดเจน โดยใช้ข้อมูลแบ่งชุดเดิมเพื่อเทียบอย่างยุติธรรม

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

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

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

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

รับ X เป็นตารางตัวเลขและ y เป็นคลาส ต้องมีตัวอย่างหลายแถวในแต่ละคลาสเพื่อประมาณค่าเฉลี่ยและ covariance ร่วม

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

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

solver
lsqr ใช้จำแนกได้แต่ไม่มี transform; svd/eigen ใช้ลดมิติได้
shrinkage
ใช้กับ lsqr/eigen เท่านั้น ลอง 'auto' เพื่อช่วยให้ covariance เสถียร
n_components
จำนวนแกนตอน transform ไม่เกิน min(จำนวน feature, จำนวนคลาส − 1)
OUTPUT

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

predict ให้คลาส predict_proba ให้โอกาส; transform ให้แกนใหม่เฉพาะ solver ที่รองรับ

สองคลาส → transform ลดได้สูงสุด 1 แกน เมื่อ solver รองรับ
CALCULATION

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

  1. 01

    หา mean ต่อคลาส และ covariance ที่ใช้ร่วมกัน พร้อม prior ของแต่ละคลาส

  2. 02

    คำนวณ discriminant score ของข้อมูลใหม่จาก mean, covariance และ prior

  3. 03

    เลือกคลาสคะแนนสูงสุด; ถ้าต้องการลดมิติ ใช้ transform กับ solver ที่รองรับ

ควรรู้อีกนิด — สมมติแต่ละคลาสมี covariance เดียวกันและขอบเขตจึงเป็นเส้นตรง

04Make it yours

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

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

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