2013-08-21 33 views
9

Tôi có một thuật toán đang chạy trên một tập các đối tượng. Thuật toán này tạo ra một giá trị điểm số quy định sự khác biệt giữa các phần tử trong tập hợp.Giá trị Clustering bởi sự gần nhau của chúng trong python (máy học?)

Kết quả được sắp xếp là một cái gì đó như thế này:

[1,1,5,6,1,5,10,22,23,23,50,51,51,52,100,112,130,500,512,600,12000,12230]

Nếu bạn đặt các giá trị này xuống trên bảng tính, bạn sẽ thấy chúng tạo thành nhóm

[1,1,5,6,1,5] [10,22,23,23] [50,51, 51,52] [100,112,130] [500,512,600] [12000,12230]

Có cách nào để lập trình các nhóm này không?

Có thể một số thuật toán phân cụm bằng thư viện học máy? Hay tôi đang suy nghĩ về điều này?

Tôi đã xem xét scikit nhưng các ví dụ của chúng quá cao cấp cho sự cố của tôi ...

Trả lời

2

Bạn có thể sử dụng phân cụm để nhóm các mục này. Bí quyết là hiểu rằng có hai thứ nguyên cho dữ liệu của bạn: thứ nguyên bạn có thể thấy và thứ nguyên "không gian" trông giống như [1, 2, 3 ... 22]. Bạn có thể tạo ma trận này trong numpy như vậy:

import numpy as np 

y = [1,1,5,6,1,5,10,22,23,23,50,51,51,52,100,112,130,500,512,600,12000,12230] 
x = range(len(y)) 
m = np.matrix([x, y]).transpose() 

Sau đó, bạn có thể thực hiện clustering trên ma trận, với:

đầu ra
from scipy.cluster.vq import kmeans 
kclust = kmeans(m, 5) 

kclust sẽ trông như thế này:

(array([[ 11, 51], 
     [ 15, 114], 
     [ 20, 12115], 
     [ 4,  9], 
     [ 18, 537]]), 21.545126372346271) 

Đối bạn, phần thú vị nhất là cột đầu tiên của ma trận, cho biết các trung tâm nằm dọc theo thứ nguyên x đó:

kclust[0][:, 0] 
# [20 18 15 4 11] 

Sau đó bạn có thể gán số điểm đó để một cụm trên cơ sở đó trong năm trung tâm nào sát nó:

assigned_clusters = [abs(cluster_indices - e).argmin() for e in x] 
# [3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 0, 0, 0] 
+0

một chức năng kmeans2 cập nhật (trong scipy.cluster.vq) bây giờ kết quả đầu ra cả hai trọng tâm và nhãn, ví dụ 'kclust, label = kmeans (m, 5)' – Sean

+0

Xin chào, Mã không hoạt động. Lỗi trong dòng đầu tiên vì lý do rõ ràng. Dòng cuối cùng cũng tạo ra một lỗi, 'cluster_indices' không được định nghĩa. Bạn có thể vui lòng giúp mã này chạy không? – gprakhar

+0

@gprakhar Sử dụng 'cluster_indices = kclust [0] [:, 0]'. – joost

17

Một lựa chọn tốt nếu bạn không biết số lượng cụm là MeanShift:

import numpy as np 
from sklearn.cluster import MeanShift, estimate_bandwidth 

x = [1,1,5,6,1,5,10,22,23,23,50,51,51,52,100,112,130,500,512,600,12000,12230] 

X = np.array(zip(x,np.zeros(len(x))), dtype=np.int) 
bandwidth = estimate_bandwidth(X, quantile=0.1) 
ms = MeanShift(bandwidth=bandwidth, bin_seeding=True) 
ms.fit(X) 
labels = ms.labels_ 
cluster_centers = ms.cluster_centers_ 

labels_unique = np.unique(labels) 
n_clusters_ = len(labels_unique) 

for k in range(n_clusters_): 
    my_members = labels == k 
    print "cluster {0}: {1}".format(k, X[my_members, 0]) 

Output cho thuật toán này:

cluster 0: [ 1 1 5 6 1 5 10 22 23 23 50 51 51 52] 
cluster 1: [100 112 130] 
cluster 2: [500 512] 
cluster 3: [12000] 
cluster 4: [12230] 
cluster 5: [600] 

Modi fying quantile biến bạn có thể thay đổi tiêu chí lựa chọn số phân nhóm

+2

Đối số đầu tiên của 'np.array' cần phải là' danh sách (zip (x, np.zeros (len (x)))) '. Nếu không, Python ném một lỗi: _TypeError: int() đối số phải là một chuỗi, một đối tượng giống như byte hoặc một số, không phải 'zip'_ – Logan

+0

Cách tiếp cận này có thể không hoạt động tốt cho một số đầu vào không dễ dàng "clusterable ", ví dụ 'x = [90, 100, 110]'. Sau đó nó sẽ thất bại với 'ValueError: Mong đợi n_neighbors> 0. Got 0' (có thể tránh được với điều chỉnh tham số). Đối với các đầu vào như vậy https://stackoverflow.com/a/18385795/942774 có lẽ là câu trả lời đơn giản hơn và tốt hơn nhiều. – hendrik

8

Không sử dụng phân nhóm cho dữ liệu 1 chiều

thuật toán Clustering được thiết kế cho dữ liệu đa biến. Khi bạn có dữ liệu 1 chiều, hãy sắp xếp và tìm kiếm các khoảng trống lớn nhất lớn nhất. Đây là tầm thường và nhanh trong 1 ngày và không thể thực hiện trong 2 ngày. Nếu bạn muốn một cái gì đó nâng cao hơn, hãy sử dụng Kernel Density Estimation (KDE) và tìm minima cục bộ để chia bộ dữ liệu.

Có một số các bản sao của câu hỏi này:

+0

Cách tiếp cận này có thể nhạy cảm với tiếng ồn. – jhegedus

+0

Ngược lại. KDE trơn tru và do đó không quá nhạy cảm với tiếng ồn. Ít hơn so với k-phương tiện được biết là rất nhạy cảm do các thuật ngữ sai số bình phương. –

+0

Thú vị, cảm ơn bạn đã chỉ ra điều này. – jhegedus

Các vấn đề liên quan