2017-01-06 4 views
3

В контексте неконтролируемого ближайших соседей с scikit-learn я реализовал свою собственную функцию расстояния, чтобы справиться со своими неопределенными точками (т.е. точка представляется в виде нормального распределения):Входные размеры для функции расстояния для ближайших соседей

def my_mahalanobis_distance(x, y): 

''' 
x: array of shape (4,) x[0]: mu_x_1, x[1]: mu_x_2, 
         x[2]: cov_x_11, x[3]: cov_x_22 
y: array of shape (4,) y[0]: mu_ y_1, y[1]: mu_y_2, 
         y[2]: cov_y_11, y[3]: cov_y_22 
'''  

    cov_inv = np.linalg.inv(np.diag(x[:2])+np.diag(y[:2])) 
    return sp.spatial.distance.mahalanobis(x[:2], y[:2], cov_inv) 

Однако, когда я устанавливаю мои ближайшие соседи:

nnbrs = NearestNeighbors(n_neighbors=1, metric='pyfunc', func=my_mahalanobis_distance) 
nearest_neighbors = nnbrs.fit(X) 

где X является (N, 4) (n_samples, n_features) массив, если я печатаю x и y в моем my_mahalanobis_distance, я получаю формы (10,) вместо (4,), как и следовало ожидать.

Пример:

добавить следующую строку в my_mahalanobis_distance:

print(x.shape) 

Тогда в моей основной:

n_features = 4 
n_samples = 10 
# generate X array: 
X = np.random.rand(n_samples, n_features) 
nnbrs = NearestNeighbors(n_neighbors=1, metric='pyfunc', func=my_mahalanobis_distance) 
nearest_neighbors = nnbrs.fit(X) 

В результате:

(10,) 
ValueError: shapes (2,) and (8,8) not aligned: 2 (dim 0) != 8 (dim 0) 

Я perfectl y понять ошибку, но я не понимаю, почему мой x.shape - (10,), а мой номер функций - 4 в X.

Я использую Python 2.7.10 и scikit учиться 0.16.1.

EDIT:

замена return sp.spatial.distance.mahalanobis(x[:2], y[:2], cov_inv) на return 1 только для возвращения тестирования:

(10,) 
(4,) 
(4,) 
(4,) 
(4,) 
(4,) 
(4,) 
(4,) 
(4,) 
(4,) 
(4,) 

Так что только первый вызов my_mahalanobis_distance неправильно. Глядя на значения x и y на первой итерации, мои наблюдения:

  • x и y идентичны

  • если я запускаю код несколько раз, x и y все еще идентичны, но их значения имеют изменения по сравнению с предыдущим прогоном.

  • Эти значения выглядят исходя из функции numpy.random.

Я бы сделал вывод, что такой первый вызов является частью отладки кода, которая не удалена.

+0

Пожалуйста, добавьте игрушечный пример с входом, желаемым выходом и фактическим выходом. –

+0

Я просто добавил игрушечный пример. – floflo29

+0

Попробуйте обновить scikit-learn. –

ответ

0

Я привышные мой my_mahalanobis_distance, чтобы справиться с этой проблемой:

def my_mahalanobis_distance(x, y): 
    ''' 
    x: array of shape (4,) x[0]: mu_x_1, x[1]: mu_x_2, 
          x[2]: cov_x_11, x[3]: cov_x_22 
    y: array of shape (4,) y[0]: mu_ y_1, y[1]: mu_y_2, 
          y[2]: cov_y_11, y[3]: cov_y_22 
    '''  

    if (x.size, y.size) == (4, 4):   

     return sp.spatial.distance.mahalanobis(x[:2], y[:2], 
              np.linalg.inv(np.diag(x[2:]) 
              + np.diag(y[2:]))) 

    # to handle the buggy first call when calling NearestNeighbors.fit() 
    else: 
     warnings.warn('x and y are respectively of size %i and %i' % (x.size, y.size)) 
     return sp.spatial.distance.euclidean(x, y) 
+0

Не могли бы вы подробнее? Поскольку мои 'x' и' y' должны иметь форму '(4,)', это не проблема. Я мог бы вернуться 1, это просто не поднять ошибку. – floflo29

+0

Да, но я вхожу в оператор 'else' только один раз (я это обеспечил) во время первого вызова (вероятно, оставшаяся часть отладки кода). Я мог бы вернуть то, что вам подходит вместо евклидова дистанции. – floflo29

+0

Да. Согласно документации 'scikit-learn': вызываемый должен принимать два массива в качестве ввода и возвращать одно значение, указывающее расстояние между ними – floflo29

1

Это не ответ, но слишком длинный для комментария. Я не могу воспроизвести ошибку.

Использование:

Python 3.5.2 и Sklearn 0.18.1

с кодом:

from sklearn.neighbors import NearestNeighbors 
import numpy as np 
import scipy as sp 
n_features = 4 
n_samples = 10 
# generate X array: 
X = np.random.rand(n_samples, n_features) 


def my_mahalanobis_distance(x, y):  
    cov_inv = np.linalg.inv(np.diag(x[:2])+np.diag(y[:2])) 
    print(x.shape) 
    return sp.spatial.distance.mahalanobis(x[:2], y[:2], cov_inv) 

n_features = 4 
n_samples = 10 
# generate X array: 
X = np.random.rand(n_samples, n_features) 
nnbrs = NearestNeighbors(n_neighbors=1, metric=my_mahalanobis_distance) 
nearest_neighbors = nnbrs.fit(X) 

Выход

(4,) 
(4,) 
(4,) 
(4,) 
(4,) 
(4,) 
(4,) 
(4,) 
(4,) 
(4,) 
Смежные вопросы