Đến nội dung chính
Học máy

Phân cụm: khoảng cách, K-means và cách đánh giá cấu trúc

Khám phá dữ liệu không có nhãn mục tiêu; hiểu chuẩn hóa, mục tiêu K-means và giới hạn của các chỉ số nội tại.

Mức giải thích

Phân cụm tìm các nhóm theo một cách biểu diễn và một tiêu chí tương tự đã chọn. Nó không tự khám phá các loại người hay các nhãn chân lý. Bài viết dùng các điểm một chiều tự tạo để quan sát cách tâm cụm thay đổi và vì sao lựa chọn khoảng cách quan trọng.

Mục tiêu học tập

  • Phân biệt phân cụm với phân loại có giám sát.
  • Thực hiện các bước gán cụm và cập nhật tâm của K-means.
  • Đánh giá cụm bằng nhiều kiểm tra thay vì chỉ một điểm số.

Tương tự theo cách biểu diễn nào?

Khác phân loại, bài toán không cung cấp target y để học ánh xạ nhãn. Ta chọn biểu diễn x và độ tương tự. Khoảng cách Euclidean nhạy với đơn vị: biến có thang hàng nghìn dễ chi phối biến chỉ nằm giữa không và một.

Chuẩn hóa, loại biến định danh không có ý nghĩa khoảng cách và kiểm tra missing values trước khi phân cụm. Nếu cần áp dụng cho dữ liệu tương lai, fit preprocessing trên dữ liệu tham chiếu và giữ lại tham số.

Vòng lặp của K-means

K-means tối thiểu hóa ∑i∥xi−μci∥22\sum_i\|x_i-\mu_{c_i}\|_2^2. Với tâm cố định, gán vào tâm gần nhất; với gán cố định, cập nhật bằng trung bình. Mã một chiều thực hiện đúng hai bước này và có giới hạn vòng lặp.

Khởi tạo khác nhau có thể dẫn đến nghiệm khác nhau. Khi một cụm không còn điểm, implementation phải có quy tắc xử lý; ví dụ giữ nguyên tâm cũ để tránh chia cho không.

Đánh giá cấu trúc thay vì chỉ giảm inertia

Inertia là tổng squared distance đến tâm; không so trực tiếp khi thay scaling hoặc tập dữ liệu. Silhouette so khoảng cách trong cụm với cụm gần khác, hợp lệ khi có ít nhất hai cụm và ít hơn số mẫu.

Kết hợp chỉ số nội tại với kiểm tra theo mục đích. Nếu có nhãn tham chiếu độc lập, dùng chỉ số so partition như adjusted Rand, nhưng đừng chọn ngầm tham số bằng nhãn rồi gọi quy trình hoàn toàn không giám sát.

Dữ liệu mới và bài thực hành

Khi dùng mô hình đã fit, biến đổi mẫu mới bằng đúng preprocessing đã lưu rồi gán theo quy tắc phù hợp. K-means hỗ trợ gán về tâm; không phải mọi thuật toán phân cụm đều có cùng cơ chế predict.

Theo dõi kích thước cụm, khoảng cách đến tâm và thay đổi đặc trưng theo thời gian. Đừng suy ra thuộc tính cá nhân nhạy cảm từ một tên cụm được đặt tùy ý.

Workflow & kiến trúc

Chỉ fit preprocessing và mô hình trên tập train. Tập test dùng phép biến đổi đã học và mô hình đã cố định để dự đoán, rồi đối chiếu với nhãn test.
01Xác định mục đích nhóm
02Chọn biểu diễn và metric
03Fit preprocessing
04Thử số cụm và khởi tạo
05Kiểm tra ổn định và ý nghĩa
Workflow minh họa · Các bước cần được điều chỉnh theo bài toán thực tế.

Ứng dụng & giới hạn

  • Khám phá cấu trúc trong embedding hoặc dữ liệu bảng.
  • Chọn đại diện để kiểm tra dữ liệu và phát hiện các nhóm cần nghiên cứu thêm.

Điểm mạnh

Có thể hỗ trợ khám phá khi chưa có nhãn mục tiêu, đồng thời làm rõ ảnh hưởng của biểu diễn và khoảng cách.

Giới hạn cần nhớ

Kết quả phụ thuộc metric, scaling và số cụm. K-means nhạy với outlier và không tự xác nhận các nhóm có ý nghĩa ngoài dữ liệu.

Thử trong một project nhỏ

LEARN BY DOING

Chạy mã rồi thêm điểm 100. So tâm và inertia, ghi vì sao thay đổi đó không đủ để kết luận số cụm đúng. Đổi khởi tạo, rồi thử xây dữ liệu một chiều không có khoảng trống rõ ràng giữa nhóm.

PYTHON · VÍ DỤ MINH HỌA
# Synthetic one-dimensional data; no external packages.
points = [0.0, 0.5, 1.0, 8.0, 8.5, 9.0]
centers = [0.0, 9.0]
for iteration in range(100):
    labels = [min(range(len(centers)), key=lambda j: (x - centers[j]) ** 2)
              for x in points]
    updated = []
    for j, previous in enumerate(centers):
        members = [x for x, label in zip(points, labels) if label == j]
        updated.append(sum(members) / len(members) if members else previous)
    converged = max(abs(a - b) for a, b in zip(centers, updated)) < 1e-10
    centers = updated
    if converged:
        break
else:
    raise RuntimeError("Iteration limit reached")
labels = [min(range(len(centers)), key=lambda j: (x - centers[j]) ** 2)
          for x in points]
inertia = sum((x - centers[j]) ** 2 for x, j in zip(points, labels))
assert centers == [0.5, 8.5] and labels == [0, 0, 0, 1, 1, 1]
print({"centers": centers, "labels": labels, "inertia": inertia})

Python chuẩn; K-means một chiều trên sáu điểm tự tạo. Giá trị inertia chỉ dùng kiểm tra phép tính, không phải chất lượng phân cụm thực tế.

Nguồn tham khảo

  1. Google — What is clustering?
  2. scikit-learn — Clustering
  3. Google — K-means clustering

KEEP EXPLORING

Đọc tiếp để nối các ý tưởng.