Cách Mình Quản Lý Clustering
Nguyên tắc tạo ra clusters nhất quán, hữu dụng từ noisy data
Clustering algorithms cho ra nhóm toán học, chưa chắc khớp với kỳ vọng con người. Data thật thì luôn có outliers không biết xếp đâu, clusters quá to để xài được, clusters quá bé chẳng mang ý nghĩa gì. Chạy algorithm xong mới là bắt đầu -- phần post-processing mới quyết định output có dùng được không.
Câu hỏi cốt lõi: "Mỗi item có kết thúc trong một cluster có ý nghĩa semantic không?"
Outliers -- tính năng chứ không phải lỗi
Nhiều người thấy outliers là cố nhét hết vào cluster nào đó cho gọn. Sai.
Phải phân biệt hai loại: "true outliers" (items thực sự unique, không giống ai) và "orphans" (items lẽ ra thuộc cluster nào đó nhưng bị bỏ sót). Orphans thì reassign vào nearest cluster dùng cosine similarity và k-NN voting. True outliers thì giữ riêng trong category "Other" rõ ràng.
Force-assign item unique vào cluster không liên quan thì cluster coherence giảm, user nhìn vào bối rối. Nhưng để orphans lang thang unassigned thì lãng phí data. Phải cân bằng.
Kiểm soát size distribution
Algorithm cho ra một cluster 500 items và mấy cluster 3 items -- kiểu phân phối này không ai xài được. Cluster 500 items thì quá rộng, phân tích chẳng có insight gì. Cluster 2 items thì thường là noise.
Định nghĩa size bounds chấp nhận được (minimum và maximum). Subdivide oversized clusters, merge undersized clusters vào nearest neighbors. Quan trọng: làm các bounds này configurable theo use case, vì mỗi dataset có đặc thù riêng.
Validate trước khi reassign
Reassign outliers thuần túy bằng distance mà không kiểm tra semantic fit thì hay ra kết quả vô lý -- kiểu đặt "apple" vào cluster "automotive parts" vì nó gần nhất về toán.
Khi reassign, verify similarity vượt ngưỡng. Dùng k-NN voting giữa neighbors chứ đừng chỉ nearest-neighbor. Chỉ reassign khi point thực sự fit. Nearest trong vector space không phải lúc nào cũng là semantically related, nhất là sau dimensionality reduction.
Lặp cho đến khi ổn định
Chạy post-processing một lần rồi dừng thì thường chưa đủ. Sau khi merge small clusters, có thể cluster mới lại quá lớn. Subdivide xong, có thể tạo ra clusters quá nhỏ. Các thao tác tương tác qua lại với nhau.
Chạy size correction iterative cho đến khi sizes ổn định hoặc đạt maximum iterations (10 là thường đủ). Log thay đổi mỗi iteration để debug. Đừng quên set giới hạn -- không thì edge cases chạy vô hạn luôn =))
Labels phải reflect nội dung thật
"Cluster 1", "Cluster 2" -- nhìn vào chẳng biết trong đó có gì. Labels tệ thì toàn bộ công sức clustering coi như bỏ.
Generate labels từ cluster content: sample representative items rồi dùng LLM tạo labels ngắn gọn, có ý nghĩa. Quan trọng là generate labels ở bước cuối cùng, sau khi tất cả post-processing xong. Labels mà generate trước cleanup thì merge/split xong labels cũ thành sai hết.
Khung quyết định
Reassign outliers hay giữ riêng?
Reassign khi:
- Similarity cao với cluster centroid (>0.7 cosine similarity)
- Nhiều nearest neighbors thuộc cùng cluster (k-NN consensus)
- Outlier có vẻ borderline, không thực sự unique
- User ưu tiên complete assignment hơn precision
Giữ riêng khi:
- Similarity với tất cả clusters thấp (dưới 0.5)
- Nearest neighbors chia đều qua nhiều clusters (không consensus)
- Point thực sự unique hoặc ambiguous
- User ưu tiên precision hơn complete assignment
Khi nào subdivide cluster lớn?
Subdivide khi:
- Size vượt maximum threshold (50+ items chẳng hạn)
- Cluster chứa sub-groups semantically distinct
- Hierarchical structure giúp user hiểu hơn
- Granularity setting yêu cầu fine-grained
Giữ nguyên khi:
- Items thực sự similar (intra-cluster similarity cao)
- Subdivision tạo ra sub-clusters nhìn tùy tiện
- User muốn broad, high-level clustering
- Cluster đại diện cho large category hợp lý
Khi nào merge small clusters?
Merge khi:
- Size dưới minimum threshold (3 items chẳng hạn)
- Centroids gần nhau, similarity cao giữa clusters
- Merged cluster vẫn coherent
- Small cluster có vẻ là noise
Giữ riêng khi:
- Cluster nhỏ nhưng đại diện category distinct, có ý nghĩa
- Merge sẽ kết hợp items không liên quan
- User muốn granular clustering
- Precision quan trọng hơn coverage
Mấy lỗi hay gặp
Threshold cố định cho mọi dataset. 100 items chạy ngon, 10,000 items thì tệ. Parameters cho English mà áp cho tiếng Việt cũng không ổn. Scale thresholds theo dataset size, test trên data representative, và làm key thresholds configurable.
Subdivision bỏ qua semantics. Cluster lớn bị chia đôi kiểu arbitrary, sub-clusters không có meaningful distinction gì. Dùng hierarchical clustering hoặc semantic-aware subdivision -- chia theo natural semantic boundaries, đừng cắt bừa.
Reassign quá mạnh tay. Mọi point đều phải có nhà, không ai được là outlier. Kết quả là clusters chứa items rõ ràng không thuộc về. Thêm similarity threshold, chấp nhận rằng một số points là genuine outliers, và surface category "Other" cho user thấy.
Không giới hạn iteration. Post-processing loop chạy mãi trên edge cases, system treo. Set maximum iterations, log khi đạt limit. Kết quả "đủ tốt" còn hơn chạy mãi không xong.
Labels generate trước cleanup. Merge/split xong thì labels cũ mô tả nội dung đã bị di chuyển -- sai hết. Luôn generate labels ở bước cuối, sau khi post-processing hoàn tất. Labels phản ánh cluster membership cuối cùng mới đúng.
Checklist đánh giá
Đang ổn nếu:
- Clusters nằm trong size bounds chấp nhận được (5-50 items chẳng hạn)
- Random samples từ mỗi cluster nhất quán về semantic
- Outliers được reassign có ý nghĩa hoặc tách riêng rõ ràng
- Labels mô tả chính xác nội dung cluster
- Chạy lại với cùng config cho kết quả nhất quán
Cần xem lại nếu:
- Một số clusters lớn hơn rất nhiều so với phần còn lại
- Clusters chứa items rõ ràng không liên quan
- Quá nhiều items kết thúc là unassigned outliers
- Labels không khớp nội dung thật trong cluster
- Kết quả mỗi lần chạy ra khác nhau, không ổn định
Tham khảo nhanh
Raw Clustering Output
|
v
+-------------------+
| Outlier Handling |
| - k-NN voting |
| - Similarity check|
| - Reassign or keep|
+-------------------+
|
v
+-------------------+
| Size Correction | <----- Lặp cho đến khi ổn định
| - Subdivide large | (tối đa 10 iterations)
| - Merge small |
+-------------------+
|
v
+-------------------+
| Final Cleanup |
| - Renumber IDs |
| - Sort by size |
+-------------------+
|
v
+-------------------+
| Label Generation |
| - Sample items |
| - LLM labeling |
| - Validate fit |
+-------------------+
| Vấn đề | Phát hiện | Giải pháp |
|---|---|---|
| Clusters quá lớn | Size > max_threshold | Recursive bisection, hierarchical split |
| Clusters quá nhỏ | Size < min_threshold | Merge vào nearest theo centroid distance |
| Outliers (recoverable) | Similarity cao với cluster | k-NN voting + threshold reassignment |
| Outliers (genuine) | Similarity thấp với tất cả | Giữ trong category "Other" |
| Labels kém | Kiểm tra thủ công | Regenerate với nhiều samples hơn, prompt tốt hơn |