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.
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?
Hai tài liệu có thể gần nhau theo từ khóa nhưng khác mục đích sử dụng. Hai lần truy cập có thể giống thời lượng nhưng khác thời điểm. Muốn gom nhóm, trước tiên phải nói đang xem những đặc trưng nào.
Tên cụm được người phân tích đặt sau khi kiểm tra ví dụ; nhãn số không mang ý nghĩa tự nhiên. Cụm số không của lần chạy này có thể tương ứng cụm số một ở lần khác.
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ố.
Biểu diễn và metric xác định khái niệm lân cận. Cosine phù hợp một số embedding theo hướng, còn Euclidean xét cả độ lớn; sau L2 normalization, squared Euclidean có quan hệ đơn điệu với cosine similarity. Không vì thế mọi thuật toán trở nên tương đương.
Trong không gian nhiều chiều, khoảng cách có thể khó phân biệt và nhiễu đặc trưng ảnh hưởng mạnh. Giảm chiều hoặc chọn đặc trưng phải đi kèm kiểm tra tính ổn định và thông tin bị mất.
Vòng lặp của K-means
Chọn vài tâm ban đầu. Mỗi điểm đi về tâm gần nhất, rồi mỗi tâm dời đến trung bình các điểm được giao. Lặp hai bước đến khi vị trí hoặc việc gán ổn định.
Nếu chọn hai tâm, thuật toán vẫn phải trả hai nhóm ngay cả khi dữ liệu không có hai nhóm tự nhiên. Số nhóm là một quyết định cần kiểm tra, không phải điều thuật toán tự biết.
K-means tối thiểu hóa . 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.
Mỗi bước không làm tăng mục tiêu nếu thực hiện chính xác, nhưng hội tụ không bảo đảm tối ưu toàn cục. K-means++ và nhiều lần khởi tạo giúp giảm rủi ro nghiệm xấu; vẫn cần ghi random seed và cấu hình.
Trung bình và squared distance nhạy với outlier. Các cụm kéo dài, mật độ khác nhau hoặc không lồi có thể không phù hợp với phân hoạch theo tâm; cân nhắc thuật toán khác dựa trên cấu trúc dự kiến.
Đánh giá cấu trúc thay vì chỉ giảm inertia
Tăng số cụm thường khiến điểm gần tâm hơn. Điều đó không có nghĩa cách chia hữu ích hơn: nếu mỗi điểm là một cụm thì khoảng cách có thể bằng không nhưng gần như không còn tóm tắt được dữ liệu.
Xem các điểm đại diện, ngoại lệ và sự ổn định khi đổi một ít dữ liệu. Hỏi nhóm có giúp tác vụ thực tế hay chỉ phản ánh thang đo của một cột.
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.
Silhouette thiên về cấu trúc tách biệt theo metric được chọn, không chứng minh các nhóm mang ý nghĩa khoa học. Với các seed hoặc bootstrap khác nhau, so partition bằng chỉ số bất biến với hoán vị nhãn; so trực tiếp số nhãn là sai.
Khi chọn biểu diễn dựa vào downstream task, cần đánh giá tác vụ đó theo protocol riêng. Kết quả phân cụm đẹp trong hai chiều sau visualization không đảm bảo khoảng cách trong không gian gốc cũng hỗ trợ cùng kết luận.
Dữ liệu mới và bài thực hành
Chạy mã để thấy các điểm nhỏ và lớn đi về hai tâm khác nhau. Sau đó thêm một điểm rất xa và xem tâm bị kéo đi. Những điểm này là bài tính minh họa, không phải dữ liệu người dùng thật.
Nếu nhóm mới xuất hiện trong tương lai, gán về tâm gần nhất có thể che khuất thay đổi đó. Cần giữ cách theo dõi khoảng cách và xem lại các điểm bất thường.
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 ý.
Độ trôi có thể làm tâm cũ không còn đại diện. Tái fit tạo nhãn cụm không tương ứng tự động với phiên bản trước; cần ánh xạ hoặc báo cáo partition mới rõ ràng. Các quyết định dựa trên cụm cần được kiểm tra lại.
Để thực hành tái lập, lưu biểu diễn, scaler, số cụm, khởi tạo, tiêu chí dừng và dữ liệu đánh giá. Một ví dụ hội tụ trên sáu số không cung cấp bằng chứng về chất lượng trên dữ liệu thực.
Workflow & kiến trúc
Ứ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ỏ
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.
# 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ế.
