Cosine similarity และการจัดกลุ่ม k-means ใน Python
การเรียนรู้แบบไม่มีผู้สอนค้นหาโครงสร้างในข้อมูลที่ไม่มีป้ายกำกับ cosine similarity วัดว่าเวกเตอร์สองตัวคล้ายกันแค่ไหน ส่วน k-means จัดจุดเป็นกลุ่มรอบจุดศูนย์กลางที่มันเรียนรู้เอง
แนวคิดแบบเข้าใจง่าย
การเรียนรู้แบบไม่มีผู้สอนค้นหาโครงสร้างในข้อมูลที่ไม่มีป้ายกำกับ cosine similarity วัดว่าเวกเตอร์สองตัวคล้ายกันแค่ไหน ส่วน k-means จัดจุดเป็นกลุ่มรอบจุดศูนย์กลางที่มันเรียนรู้เอง
วัดว่าเวกเตอร์สองตัวคล้ายกันแค่ไหนด้วย cosine similarity และจัดกลุ่มข้อมูลที่ไม่มีป้ายกำกับด้วย k-means
ประเด็นสำคัญ
- cosine similarity ไม่สนความยาว เทียบเฉพาะทิศทาง จึงเหมาะกับข้อความและ embedding
- k-means ต้องรู้จำนวนกลุ่ม k ล่วงหน้า
- ศูนย์กลางเริ่มต้นอาจทำให้ผลลัพธ์ต่างกัน จึงมักรัน k-means หลายครั้ง
- กลุ่มได้มาจากข้อมูลล้วน ๆ ไม่ต้องใช้ป้ายกำกับ
ควรใช้เมื่อใด?
- เข้าใจสิ่งที่เกิดขึ้นภายในโครงข่ายประสาทเทียมและไลบรารี AI
- เข้าใจแนวคิดก่อนลงมือเขียนเองในโจทย์ที่เกี่ยวข้อง
- เตรียมตัวสำหรับคอร์สแมชชีนเลิร์นนิง การสัมภาษณ์งาน และโปรเจกต์
ลองดูการทำงานจริง
กด ทีละขั้น เพื่อสลับสองขั้นตอนของ k-means หรือกด เล่น เพื่อทำซ้ำจนไม่มีอะไรเปลี่ยน หมุนเวกเตอร์ด้านขวาเพื่อเปลี่ยน cosine similarity
โค้ดตัวอย่าง
import math
# Cosine similarity compares directions: 1 = same direction, 0 = unrelated.
def cosine(a, b):
dot = sum(x * y for x, y in zip(a, b))
return dot / (math.sqrt(sum(x * x for x in a)) * math.sqrt(sum(y * y for y in b)))
print("cos(doc1, doc2):", round(cosine([1, 2, 0], [2, 4, 0]), 3))
print("cos(doc1, doc3):", round(cosine([1, 2, 0], [0, 0, 3]), 3))
# k-means: assign points to the nearest centre, then move each centre to its points' mean.
points = [1, 2, 3, 10, 11, 12]
centres = [1.0, 2.0]
for step in range(1, 4):
groups = [[], []]
for p in points:
nearest = min(range(len(centres)), key=lambda i: abs(p - centres[i]))
groups[nearest].append(p)
centres = [sum(g) / len(g) for g in groups]
print(f"step {step}: centres={[round(c, 2) for c in centres]} groups={groups}")
ผลลัพธ์ที่คาดหวัง
cos(doc1, doc2): 1.0
cos(doc1, doc3): 0.0
step 1: centres=[1.0, 7.6] groups=[[1], [2, 3, 10, 11, 12]]
step 2: centres=[2.0, 11.0] groups=[[1, 2, 3], [10, 11, 12]]
step 3: centres=[2.0, 11.0] groups=[[1, 2, 3], [10, 11, 12]]
หลักการทำงาน
cosine() หารผลคูณจุดด้วยความยาวของเวกเตอร์ทั้งสอง doc2 (ทิศเดียวกับ doc1) จึงได้ 1 และ doc3 (ไม่มีคำร่วมกัน) ได้ 0 ส่วน k-means ทำซ้ำสองขั้น คือจัดแต่ละจุดเข้าศูนย์กลางที่ใกล้ที่สุด แล้วย้ายศูนย์กลางไปที่ค่าเฉลี่ยของจุดในกลุ่ม หลังขั้นที่ 2 ไม่มีอะไรเปลี่ยนอีก แปลว่าลู่เข้าแล้ว
เปลี่ยนค่าและรันโปรแกรมด้วย คอมไพเลอร์ Python ออนไลน์ของ CodeUtility โดยไม่ต้องติดตั้ง Python
แบบฝึกหัด
ลองเปลี่ยน input และทดสอบกรณีขอบก่อนใช้ชุดข้อมูลที่ใหญ่ขึ้น
- เปลี่ยนอินพุตหรือน้ำหนัก แล้วลองทายผลลัพธ์ก่อนรัน
- พิมพ์ค่าระหว่างทางออกมาเพื่อดูการคำนวณทีละขั้น
- แก้โจทย์ที่ลิงก์ไว้ด้านล่างเพื่อเขียนแนวคิดนี้ด้วยตัวเอง
ฝึกด้วยโจทย์
ใช้สิ่งที่เรียนในบทนี้แก้ปัญหาจริง ทุกโจทย์รันในเบราว์เซอร์ พร้อมการทดสอบทันทีและรีวิวจาก AI
- ความคล้ายคลึงโคไซน์ วัดว่าเวกเตอร์สองตัวคล้ายกันแค่ไหนจากมุมระหว่างกัน แบบเดียวกับที่เสิร์ชเอนจินเปรียบเทียบ embedding ง่าย
- การจัดกลุ่มแบบ K-means แบ่งจุดออกเป็น k กลุ่มโดยกำหนดจุดให้กับเซนทรอยด์ที่ใกล้ที่สุดและย้ายเซนทรอยด์ซ้ำไปเรื่อยๆ ปานกลาง