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

k-Nearest Neighbors

ถามเพื่อนบ้านที่อยู่ใกล้ที่สุด

LEARNING LEVEL1
พื้นฐานควรรู้มาก่อน · ระยะห่างและการปรับสเกลข้อมูล
ลองใน Playground

01Overall Concept

OVERALL CONCEPT

ไอเดียหลัก — k-Nearest Neighbors หรือ kNN ตัดสินข้อมูลใหม่ด้วยการถามตัวอย่างที่อยู่ใกล้ที่สุด ถ้าเพื่อนบ้านส่วนใหญ่เป็นกลุ่มใด ก็ทำนายเป็นกลุ่มนั้น หรือถ้าเป็นตัวเลขก็ใช้ค่าเฉลี่ยของเพื่อนบ้าน

ลองนึกภาพว่า — ถ้าเจอผลไม้ที่ไม่รู้จัก เราอาจนำไปวางใกล้ผลไม้ตัวอย่างแล้วดูว่าเพื่อนบ้านมีสี ขนาด และรูปทรงคล้ายชนิดใด วิธีนี้ไม่ต้องสร้างกฎยาว ๆ ล่วงหน้า

ตัวอย่างการนำไปใช้ — จำแนกลายมือ แนะนำสิ่งของจากคนที่มีพฤติกรรมคล้ายกัน หรือใช้เป็นโมเดลเบื้องต้นกับข้อมูลขนาดไม่ใหญ่มาก

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

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

kNN เป็นหนึ่งในอัลกอริทึมที่เข้าใจง่ายที่สุด

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

แทนที่จะสร้างสมการ เราไปดูนักเรียนที่มีบุคลิกคล้ายเขาที่สุด 5 คน

ถ้าใน 5 คนนี้

4 คนชอบวิทยาศาสตร์ 1 คนชอบศิลปะ

เราก็ทายว่านักเรียนใหม่มีแนวโน้มชอบวิทยาศาสตร์

ตัว k ก็คือจำนวนเพื่อนบ้านที่เราจะถาม

k = 1 → ดูคนที่ใกล้ที่สุดคนเดียว k = 5 → ดู 5 คน k = 20 → ดู 20 คน

ถ้า k เล็กเกินไป โมเดลอาจไวต่อ Noise มาก เช่นเจอเพื่อนบ้านแปลกๆ คนเดียวก็ตัดสินผิด

ถ้า k ใหญ่เกินไป ก็อาจกลืนความแตกต่างของกลุ่มเล็กๆ ไป

อีกเรื่องสำคัญคือคำว่า “ใกล้” ต้องนิยามผ่านระยะทางของข้อมูล ดังนั้นการจัด Scale ของข้อมูลสำคัญมาก

เช่น อายุ 30 กับ 35 ต่างกัน 5 แต่รายได้ 30,000 กับ 100,000 ต่างกัน 70,000 ถ้าไม่จัด Scale ตัวรายได้อาจครองทุกอย่าง

ภาพจำ: อยากรู้ว่าคนนี้เป็นพวกไหน ก็หันไปถามคนที่ยืนรอบตัวเขา

03How it works

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

  1. เตรียมข้อมูลเพื่อนบ้านให้เทียบกันได้

    สมมติ X เป็นคะแนนกิจกรรมวิทยาศาสตร์และศิลปะของนักเรียน ส่วน y คือวิชาที่ชอบ แบ่งชุดฝึกและทดสอบก่อน ถ้าต้องเพิ่มอายุหรือรายได้ ต้องปรับสเกลด้วย StandardScaler ที่เรียนจาก train เท่านั้น ไม่เช่นนั้นคอลัมน์ที่มีตัวเลขใหญ่จะครองระยะทางทั้งหมด

  2. ตอนฝึกยังไม่สร้างสูตรซับซ้อน

    KNeighborsClassifier เก็บข้อมูลฝึกไว้เพื่อใช้ค้นหาเพื่อนบ้าน เมื่อมีนักเรียนใหม่จึงค่อยคำนวณระยะจาก feature ของเขาไปยังคนในชุดฝึก แล้วเรียงจากใกล้ไปไกล ดังนั้น fit มักเบา แต่การ predict อาจช้าลงเมื่อข้อมูลสะสมมาก

  3. ให้เพื่อนบ้านช่วยตอบ

    ถ้า n_neighbors=5 จะใช้ห้าคนใกล้ที่สุด ถ้าสี่คนชอบวิทยาศาสตร์และหนึ่งคนชอบศิลปะ เมื่อ weights='uniform' จะตอบวิทยาศาสตร์และให้สัดส่วน 4/5 สำหรับคลาสนั้น หาก weights='distance' คนที่ใกล้กว่าจะมีน้ำหนักมากกว่า ตัวเลขสัดส่วนนี้ยังไม่ใช่การรับรองความน่าจะเป็นในโลกจริง

  4. เริ่มลงมือและหมุนสามปุ่ม

    ใช้ make_pipeline(StandardScaler(), KNeighborsClassifier(n_neighbors=5, weights='uniform', p=2)) แล้ว fit(X_train, y_train) n_neighbors คือ k, weights คือวิธีรวมเสียง และ p=2 ใช้ระยะ Euclidean ส่วน p=1 ใช้ผลรวมระยะห่างแต่ละแกน อย่าเลือก k มากกว่าจำนวนแถวฝึกในแต่ละ fold

  5. เลือกเพื่อนบ้านจากผลทดสอบ

    ลอง k เช่น 3, 5, 11, 21 ผ่าน cross-validation ภายใน train แล้วตรวจ accuracy และ confusion matrix บน test k เล็กมักไวต่อจุดผิดปกติ ส่วน k ใหญ่เกินไปอาจกลืนกลุ่มเล็ก หากหลาย feature ไม่เกี่ยวกับคำตอบ ลองคัดออก เพราะคำว่าใกล้จะเสียความหมายเมื่อเทียบข้อมูลที่ไม่ช่วยบอกความคล้ายจริง

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

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

DATA INX · featuresy · targetX = [คะแนนกิจกรรมวิทยาศาสตร์, คะแนนศิลปะ] · y = วิชาที่ชอบ
CALCULATEk-Nearest Neighbors
n_neighbors (k)metricweights
RESULT0.800.150.05class / probabilityk=5, uniform: วิทยาศาสตร์ 4 คน / ศิลปะ 1 คน → วิทยาศาสตร์
เส้นทางของข้อมูล: จากค่าที่รับเข้า ผ่านการคำนวณด้วยพารามิเตอร์ ไปเป็นผลลัพธ์
INPUT

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

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

X = [คะแนนกิจกรรมวิทยาศาสตร์, คะแนนศิลปะ] · y = วิชาที่ชอบ
PARAMETERS

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

n_neighbors (k)
จำนวนเพื่อนบ้านที่นำมาตัดสิน
metric
สูตรระยะห่าง เช่น Euclidean หรือ Manhattan
weights
ให้ทุกเพื่อนเสียงเท่ากันหรือให้จุดใกล้มีน้ำหนักมากกว่า
OUTPUT

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

ได้ป้ายคลาสหรือค่าตัวเลขหนึ่งค่าต่อแถว และสามารถดูระยะกับดัชนีของเพื่อนบ้านได้

k=5, uniform: วิทยาศาสตร์ 4 คน / ศิลปะ 1 คน → วิทยาศาสตร์
CALCULATION

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

  1. 01

    คำนวณระยะจากข้อมูลใหม่ไปยังข้อมูลฝึกทุกแถวด้วย metric ที่เลือก

  2. 02

    เรียงระยะจากน้อยไปมากและหยิบเฉพาะ k แถวแรก

  3. 03

    classification ใช้การโหวต ส่วน regression ใช้ค่าเฉลี่ย โดยอาจถ่วงน้ำหนักตามระยะ

ควรรู้อีกนิด — ทำนายช้าเมื่อข้อมูลใหญ่ ไวต่อสเกล feature และมิติสูงทำให้ระยะทางมีความหมายน้อยลง

04Make it yours

Python · scikit-learn
# ติดตั้ง: pip install numpy scikit-learn matplotlibfrom sklearn.neighbors import KNeighborsClassifierfrom 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 = KNeighborsClassifier(n_neighbors=7)model.fit(X_train, y_train)pred = model.predict(X_test)print("Accuracy:", accuracy_score(y_test, pred))

โค้ดเปลี่ยนตามค่าที่เลือกใน Playground · แต่ละภาษาใช้ข้อมูลตัวอย่างตามที่ระบุในโค้ด

05Learn by playing

ปรับ จำนวนเพื่อนบ้าน (k) แล้วสังเกตรูปแบบคำทำนายและตัวชี้วัดที่คำนวณใหม่ทันที

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

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