01 Overall Concept
ไอเดียหลัก — K-Means ช่วยจัดของที่คล้ายกันให้อยู่กลุ่มเดียวกันโดยไม่ต้องมีคำตอบกำกับ เราบอกเพียงว่าต้องการกี่กลุ่ม แล้วโมเดลจะหาจุดศูนย์กลางและจัดสมาชิกให้ใกล้ศูนย์กลางของกลุ่มตัวเองมากที่สุด
ลองนึกภาพว่า — ลองเทลูกปัดหลายสีและหลายขนาดลงบนโต๊ะ แล้ววางถ้วย K ใบ ลูกปัดแต่ละเม็ดไปหาถ้วยที่ใกล้ที่สุด จากนั้นเราย้ายถ้วยไปกลางกองลูกปัด ทำซ้ำจนถ้วยและสมาชิกแทบไม่ขยับ
ตัวอย่างการนำไปใช้ — แบ่งกลุ่มลูกค้าตามพฤติกรรม ลดจำนวนสีในภาพ จัดกลุ่มเอกสารที่คล้ายกัน หรือสำรวจว่าข้อมูลมีโครงสร้างซ่อนอยู่แบบใด
02 อธิบายภาษาคนเข้าใจง่ายๆ
K-Means ต่างจากตัวอื่นหลายตัว เพราะเราไม่ได้มี “คำตอบถูก” ให้มันเรียนก่อน
สมมติเรามีลูกค้า 100,000 คน
เรารู้ข้อมูลว่าแต่ละคน
ซื้อกี่ครั้ง ใช้เงินเท่าไร เข้าร้านบ่อยแค่ไหน ชอบสินค้าแบบไหน
แต่เราไม่รู้ว่าควรแบ่งลูกค้าเป็นกลุ่มอะไร
เราบอก K-Means ว่า
“ช่วยแบ่งลูกค้าเป็น 4 กลุ่มให้หน่อย”
มันจะเริ่มจากสร้างจุดศูนย์กลาง 4 จุด
จากนั้นลูกค้าแต่ละคนจะถูกส่งไปอยู่กับจุดศูนย์กลางที่ใกล้ที่สุด
หลังจากนั้นจุดศูนย์กลางจะขยับไปตรงค่าเฉลี่ยของสมาชิกในกลุ่ม
แล้วจัดกลุ่มใหม่
ขยับอีก
จัดใหม่อีก
ทำซ้ำจนกลุ่มเริ่มนิ่ง
สุดท้ายเราอาจได้ว่า
Cluster 1 = ซื้อบ่อย ใช้เงินเยอะ Cluster 2 = ซื้อบ่อย แต่ยอดต่อครั้งต่ำ Cluster 3 = ซื้อไม่บ่อย แต่ยอดสูง Cluster 4 = ซื้อไม่บ่อยและยอดต่ำ
จากนั้นนักการตลาดถึงค่อยมาตั้งชื่อว่า
VIP Regular Big Spender Dormant
สิ่งสำคัญคือ K-Means ไม่รู้ความหมายของกลุ่ม
มันรู้แค่ว่า
“คนพวกนี้ดูคล้ายกัน”
มนุษย์ต้องเป็นคนตีความต่อ
ข้อจำกัดคือเราต้องบอกจำนวนกลุ่ม K ก่อน เช่น 3, 4 หรือ 5 และมันมักชอบกลุ่มที่มีรูปร่างค่อนข้างเป็นก้อนกลมๆ ถ้าข้อมูลมีรูปทรงประหลาดก็อาจแบ่งได้ไม่ดี
ภาพจำ: เอาคนทั้งหมดลงสนาม แล้วตั้งธง 4 ธง ทุกคนเดินไปหาธงที่ใกล้ที่สุด จากนั้นย้ายธงไปกลางกลุ่ม ทำซ้ำจนทุกอย่างลงตัว
03 How it works
ค่อยๆ ทำไปด้วยกัน ตั้งแต่ข้อมูลแถวแรกจนถึงการตรวจคำตอบ
เริ่มจากลูกค้าที่เรายังไม่มีชื่อกลุ่มให้
ให้ X เป็นตารางจำนวนครั้งซื้อและยอดใช้จ่ายในช่วงเวลาเดียวกัน หนึ่งคนต่อหนึ่งแถว เช่น [[2, 1000], [10, 9000], ...] ไม่ต้องมี y และอย่าใส่รหัสลูกค้าเป็น feature ตรวจค่าที่ขาดและจุดผิดปกติก่อน หากยอดใช้จ่ายต่างกันมาก อาจลองแปลง log1p แล้วค่อยปรับสเกล
ตั้งสนามให้ทุกคอลัมน์มีเสียง
ใช้ StandardScaler เพื่อให้หลักพันบาทไม่กลบจำนวนครั้งซื้อ เก็บ scaler ไว้ใช้กับลูกค้าใหม่ จากนั้นเลือก n_clusters=4 หมายถึงต้องการสี่กลุ่ม เริ่มด้วย KMeans(n_clusters=4, init='k-means++', n_init=10, random_state=42) โดย k-means++ ช่วยเลือกตำแหน่งตั้งต้นให้กระจายกัน
ให้แต่ละคนเดินไปหาธงใกล้สุด
ในแต่ละรอบ โมเดลคำนวณระยะจากลูกค้าทุกคนถึง centroid ทุกจุด แล้วให้ label ตามจุดที่ใกล้ที่สุด ระยะนี้มาจาก feature ที่ปรับสเกลแล้ว ไม่ใช่ความรู้สึกว่าเป็นลูกค้า VIP เมื่อแบ่งเสร็จจึงรู้ว่า centroid แต่ละจุดมีสมาชิกเป็นใครบ้าง
ย้ายธงแล้วเริ่มรอบใหม่
คำนวณค่าเฉลี่ยของสมาชิกแต่ละกลุ่มแล้วเลื่อน centroid ไปตรงนั้น ตัวอย่างบนพิกัดที่ปรับสเกลแล้ว ถ้าสมาชิกสองจุดคือ [0, 0] และ [2, 4] จุดกลางใหม่คือ [1, 2] จากนั้นจัดสมาชิกใหม่ ทำซ้ำจนเข้าเกณฑ์ tol หรือครบ max_iter ส่วน n_init=10 คือทดลองจุดเริ่มต้นสิบชุดและเลือกชุดที่ผลรวมระยะยกกำลังสองหรือ inertia ต่ำสุด
รับผลแล้วแปลเป็นภาษาธุรกิจ
เรียก labels = model.fit_predict(X_scaled) ได้หมายเลขกลุ่มต่อแถว และ cluster_centers_ ได้พิกัดศูนย์กลาง ใช้ scaler.inverse_transform ถ้าต้องการกลับเป็นหน่วยเดิม แล้วเทียบยอดเฉลี่ยและขนาดของแต่ละกลุ่มก่อนตั้งชื่อ VIP หรือ Regular หมายเลข 0–3 เป็นเพียงชื่อชั่วคราว ไม่ได้เรียงความสำคัญ และอาจสลับกันเมื่อฝึกใหม่
ลอง K หลายค่าแล้วดูว่ากลุ่มใช้ได้ไหม
ทดลอง K=2 ถึง 6 เปรียบเทียบ silhouette score ขนาดกลุ่ม ความเสถียรเมื่อเริ่มใหม่ และความหมายทางธุรกิจ Inertia ลดลงตาม K ที่เพิ่มจึงใช้เลือก K เพียงอย่างเดียวไม่ได้ ลูกค้าใหม่ต้องผ่าน scaler เดิมแล้วใช้ predict เพื่อเข้ากลุ่มเดิมโดยไม่ย้าย centroid ถ้าจะให้กลุ่มปรับตามพฤติกรรมใหม่ ต้องวางรอบฝึกใหม่และตรวจความหมายกลุ่มอีกครั้ง
ข้อมูล พารามิเตอร์ และภาพรวมการคำนวณ
n_clusters (K)max_itern_initข้อมูลที่รับเข้ามา
รับ X เป็นตารางตัวเลขเท่านั้น ไม่รับ y เพราะไม่มีคำตอบกำกับ หนึ่งแถวคือหนึ่งสิ่งที่ต้องการจัดกลุ่ม และควรปรับสเกลทุกคอลัมน์ให้ใกล้กัน
X = [จำนวนครั้งซื้อ, ยอดใช้จ่าย] · ไม่มี yพารามิเตอร์ที่ใช้
- n_clusters (K)
- จำนวนกลุ่มและจำนวน centroid ที่ต้องการ
- max_iter
- จำนวนรอบสูงสุดของการจับกลุ่มและย้ายศูนย์กลาง
- n_init
- จำนวนครั้งที่ลองจุดเริ่มต้นใหม่ แล้วเลือกผลที่ดีที่สุด
ผลลัพธ์ที่ได้
ได้ cluster label ต่อหนึ่งแถว ตำแหน่ง centroids และ inertia ซึ่งเป็นผลรวมระยะกำลังสองภายในกลุ่ม
K=4 → label 0–3 และ centroid ทั้ง 4 จุดคำนวณทีละขั้น
- 01
วาง centroid K จุด แล้วคำนวณระยะจากข้อมูลทุกแถวไปยัง centroid ทุกจุด
- 02
กำหนด label จาก centroid ที่ใกล้ที่สุด แล้วคำนวณค่าเฉลี่ยใหม่ของสมาชิกในแต่ละกลุ่ม
- 03
ย้าย centroid ไปค่าเฉลี่ยและทำซ้ำจนตำแหน่งนิ่งหรือครบ max_iter จากนั้นเลือก run ที่ inertia ต่ำสุด
ควรรู้อีกนิด — K ต้องเลือกเอง และ Inertia มักลดลงเมื่อเพิ่ม K จึงไม่ควรใช้ตัวเลขนี้เลือก K เพียงอย่างเดียว เทคนิคนี้เหมาะกับกลุ่มค่อนข้างกลม ไวต่อ outlier และสเกลของข้อมูล ถ้าหน่วยต่างกันมาก ควรปรับสเกลก่อน
04 Make it yours
# ติดตั้ง: pip install numpy pandas scikit-learn matplotlibimport pandas as pdimport matplotlib.pyplot as pltfrom sklearn.cluster import KMeans # ดาวน์โหลด sample.csv จาก Playground ไว้ข้างไฟล์นี้df = pd.read_csv("sample.csv")X = df[["x", "y"]] # เปลี่ยนชื่อคอลัมน์เพื่อใช้ข้อมูลของคุณ model = KMeans( n_clusters=3, # จำนวนกลุ่ม: ลองเปลี่ยน 2–6 max_iter=20, # จำนวนรอบสูงสุด n_init=10, # ลองจุดเริ่มต้นหลายชุด ลดโอกาสติดคำตอบที่ไม่ดี random_state=42, # ล็อก seed ให้รันซ้ำได้)labels = model.fit_predict(X)print("Inertia:", model.inertia_)plt.scatter(X.x, X.y, c=labels, cmap="viridis")plt.scatter(*model.cluster_centers_.T, marker="X", s=150)plt.show()โค้ดอัปเดตตามพารามิเตอร์ใน Playground ด้านล่าง · เปลี่ยนไฟล์และคอลัมน์เพื่อใช้ข้อมูลของคุณ
05 Learn by playing
ลองเพิ่มหรือลด K แล้วสังเกตว่ากลุ่มและ Inertia เปลี่ยนอย่างไร
สี = กลุ่มที่โมเดลจัดให้ · + = ศูนย์กลาง
ข้อมูลสังเคราะห์ 150 จุด มี 2 features และ 3 กลุ่ม ใช้ seed 42 เพื่อให้ทดลองซ้ำได้ Playground ใช้ K-Means แบบเริ่มต้นชุดเดียว; Python ใช้ scikit-learn พร้อม n_init=10 จึงอาจได้ศูนย์กลางและ Inertia ต่างกัน ผลนี้ใช้เพื่อเรียนรู้ ไม่ใช่ benchmark บนข้อมูลจริง