2015-02-09 35 views
10

Mam tablicę 13,876 (13 876) wartości od 0 do 1. Chciałbym zastosować sklearn.cluster.KMeans tylko do tego wektora, aby znaleźć różne klastry, w których wartości są pogrupowane. Wydaje się jednak, że KMeans działa z tablicą wielowymiarową, a nie z jednowymiarowymi. Sądzę, że istnieje pewna sztuczka, która sprawi, że zadziała, ale nie wiem jak. Widziałem, że KMeans.fit() akceptuje „X: Tablica lub podobny rzadki matrycy, kształt = (n_samples, n_features)”, ale chce n_samples być większy niż jedenScikit-learn: Jak uruchomić KMeans na jednowymiarowej tablicy?

Próbowałem oddanie moją tablicę na ciągu np.zeros() Macierz i uruchom KMeans, ale następnie umieszcza wszystkie wartości inne niż null w klasie 1, a reszta w klasie 0.

Czy ktoś może pomóc w uruchomieniu tego algorytmu na jednowymiarowej tablicy? Wielkie dzięki!

Odpowiedz

18

Masz wiele próbek 1 funkcji, dzięki czemu można przekształcić tablicę do (13,876, 1) przy użyciu numpy na reshape:

from sklearn.cluster import KMeans 
import numpy as np 
x = np.random.random(13876) 

km = KMeans() 
km.fit(x.reshape(-1,1)) # -1 will be calculated to be 13876 here 
+0

To działało jak czar, ten szczegół got me zatrzymany przez jedną godzinę! – iamgin

+0

Jeśli ktoś używa MiniBatchKmeans na tego rodzaju kształcie danych, otrzymuje bardzo różne wyniki. Czy to oczekiwane zachowanie? – marscher

+0

jest to związane ze stanem losowym. Jeśli ktoś to naprawi, otrzyma takie same wyniki. – marscher

3

Przeczytaj o Jenks Natural Breaks. Funkcja w Pythonie znaleźć link z artykułu:

def get_jenks_breaks(data_list, number_class): 
    data_list.sort() 
    mat1 = [] 
    for i in range(len(data_list) + 1): 
     temp = [] 
     for j in range(number_class + 1): 
      temp.append(0) 
     mat1.append(temp) 
    mat2 = [] 
    for i in range(len(data_list) + 1): 
     temp = [] 
     for j in range(number_class + 1): 
      temp.append(0) 
     mat2.append(temp) 
    for i in range(1, number_class + 1): 
     mat1[1][i] = 1 
     mat2[1][i] = 0 
     for j in range(2, len(data_list) + 1): 
      mat2[j][i] = float('inf') 
    v = 0.0 
    for l in range(2, len(data_list) + 1): 
     s1 = 0.0 
     s2 = 0.0 
     w = 0.0 
     for m in range(1, l + 1): 
      i3 = l - m + 1 
      val = float(data_list[i3 - 1]) 
      s2 += val * val 
      s1 += val 
      w += 1 
      v = s2 - (s1 * s1)/w 
      i4 = i3 - 1 
      if i4 != 0: 
       for j in range(2, number_class + 1): 
        if mat2[l][j] >= (v + mat2[i4][j - 1]): 
         mat1[l][j] = i3 
         mat2[l][j] = v + mat2[i4][j - 1] 
     mat1[l][1] = 1 
     mat2[l][1] = v 
    k = len(data_list) 
    kclass = [] 
    for i in range(number_class + 1): 
     kclass.append(min(data_list)) 
    kclass[number_class] = float(data_list[len(data_list) - 1]) 
    count_num = number_class 
    while count_num >= 2: # print "rank = " + str(mat1[k][count_num]) 
     idx = int((mat1[k][count_num]) - 2) 
     # print "val = " + str(data_list[idx]) 
     kclass[count_num - 1] = data_list[idx] 
     k = int((mat1[k][count_num] - 1)) 
     count_num -= 1 
    return kclass 

Użyj i wizualizacja:

import numpy as np 
import matplotlib.pyplot as plt 

def get_jenks_breaks(...):... 

x = np.random.random(30) 
breaks = get_jenks_breaks(x, 5) 

for line in breaks: 
    plt.plot([line for _ in range(len(x))], 'k--') 

plt.plot(x) 
plt.grid(True) 
plt.show() 

Wynik: enter image description here