2015-06-04 4 views
2

Моего объекта данных является экземпляром:Более эффективный способ получить ближайший центр

class data_instance: 
    def __init__(self, data, tlabel): 
     self.data = data # 1xd numpy array 
     self.true_label = tlabel # integer {1,-1} 

До сих пор в коде, у меня есть список под названием data_history полных с data_istance и набором centers (Numpy массива с формой (K, d)).

Для данного data_instance new_data, я хочу:

  • 1/Получить ближайший центр к new_data от centers (евклидова расстояния) пусть это будет называется Nearest_center.

  • 2/Итерация корыта data_history и:

    • 2.1/выбора элементов, где ближайший центр является Nearest_center (результат 1 /) в список, который называется neighbors.
    • 2.2/Получить ярлыки объекта в neighbors.

Беллоу мой код, который работает, но это стали медленно, и я ищу что-то более эффективное.

Мой код

Для 1/

def getNearestCenter(data,centers): 

    if centers.shape != (1,2): 
     dist_ = np.sqrt(np.sum(np.power(data-centers,2),axis=1)) # This compute distance between data and all centers 

     center = centers[np.argmin(dist_)] # this return center which have the minimum distance from data 

    else: 
     center=centers[0] 
    return center 

Для 2/(Оптимизировать)

def getLabel(dataPoint, C, history): 

    labels = [] 
    cluster = getNearestCenter(dataPoint.data,C) 
    for x in history: 
     if np.all(getNearestCenter(x.data,C) == cluster): 
      labels.append(x.true_label) 
    return labels 
+0

Одна простая вещь, чтобы сделать это вместо вычисления евклидова расстояния между 'np.array ([данные] * LEN (центры))' и 'centers', просто использовать абсолютное значение: 'dist_ = np.abs (np.array ([данные] * len (центры)) - центры. Минимальное значение обоих векторов будет одинаковым. Это, вероятно, не будет значительной частью вашей среды выполнения, но каждый бит помогает. –

+0

Вы делаете 'np.array ([data] * len (центры))' просто для того, чтобы реплицировать вектор 1 на d в ​​массив k by d? Вам не нужно это делать, у Numpy есть [интеллектуальное вещание в массиве] (http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html), поэтому вы должны иметь возможность делать «данные» - центров или, возможно, «np.array (data) - центров». –

+0

@AhmedFasih Спасибо за комментарии, чувак, но я думаю, что основная проблема связана с методом getLabel (dataPoint, C, history) ' – farhawa

ответ

1

Вы должны лучше использовать оптимизированные cdist из scipy.spatial, который является более эффективным, чем его расчета с NumPy,

from scipy.spatial.distance import cdist 

dist = cdist(data, C, metric='euclidean') 
dist_idx = np.argmin(dist, axis=1) 

Еще более элегантное решение заключается в использовании scipy.spatial.cKDTree (как было отмечено @Saullo Кастро в комментариях) , что может быть быстрее для большого набора данных,

from scipy.spatial import cKDTree 

tr = cKDTree(C) 
dist, dist_idx = tr.query(data, k=1) 
1

Нашел:

dist_ = np.argmin(np.sqrt(np.sum(np.power(data[:, None]-C,2),axis=2)),axis=1) 

Это должно вернуть индекс ближайшего центра в centers с каждой точки данных data.