Как разрешить sklearn K ближайшим соседям использовать пользовательскую метрику расстояния?

У меня есть пользовательская метрика расстояния, которую мне нужно использовать для KNN, K Nearest Neighbors.

Я попытался выполнить это, но не могу заставить его работать по какой-то причине.

Я бы предположил, что метрика расстояния должна принимать два вектора/массива одинаковой длины, как я написал ниже:

import sklearn 
from sklearn.neighbors import NearestNeighbors
import numpy as np
import pandas as pd

def d(a,b,L):
    # Inputs: a and b are rows from a data matrix   
    return a+b+2+L

knn=NearestNeighbors(n_neighbors=1,
                 algorithm='auto',
                 metric='pyfunc',
                 func=lambda a,b: d(a,b,L)
                 )


X=pd.DataFrame({'b':[0,3,2],'c':[1.0,4.3,2.2]})
knn.fit(X)

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

ValueError: Unknown metric pyfunc. Valid metrics are ['euclidean', 'l2', 'l1', 'manhattan', 'cityblock', 'braycurtis', 'canberra', 'chebyshev', 'correlation', 'cosine', 'dice', 'hamming', 'jaccard', 'kulsinski', 'mahalanobis', 'matching', 'minkowski', 'rogerstanimoto', 'russellrao', 'seuclidean', 'sokalmichener', 'sokalsneath', 'sqeuclidean', 'yule', 'wminkowski'], or 'precomputed', or a callable

Однако я вижу то же самое в вопросе, который я цитировал. Любые идеи о том, как заставить это работать на sklearn version 0.14? Я не знаю о каких-либо различиях в версиях.

Спасибо.


person makansij    schedule 22.12.2015    source источник
comment
также ваша функция расстояния бесполезна, она вернет вектор, тогда как ей нужно вернуть одно значение   -  person maxymoo    schedule 22.12.2015


Ответы (1)


Документация на самом деле красивая ясно об использовании метрического аргумента:

метрика: строка или вызываемая, по умолчанию «минковский»

метрика, используемая для расчета расстояния. Можно использовать любую метрику из scikit-learn или scipy.spatial.distance.

Если метрика является вызываемой функцией, она вызывается для каждой пары экземпляров (строк) и записывается результирующее значение. Вызываемый объект должен принимать на вход два массива и возвращать одно значение, указывающее расстояние между ними. Это работает для метрик Scipy, но менее эффективно, чем передача имени метрики в виде строки.

Таким образом (как и в сообщении об ошибке), metric должен быть вызываемым, а не строкой. И он должен принимать два аргумента (массива) и возвращать один. Какова ваша lambda функция.

Таким образом, ваш код можно упростить до:

import sklearn
from sklearn.neighbors import NearestNeighbors
import numpy as np
import pandas as pd

def d(a,b,L):
    return a+b+2+L

knn=NearestNeighbors(n_neighbors=1,
                 algorithm='auto',
                 metric=lambda a,b: d(a,b,L)
                 )
X=pd.DataFrame({'b':[0,3,2],'c':[1.0,4.3,2.2]})
knn.fit(X)
person Community    schedule 22.12.2015
comment
Спасибо. Документация, которую я видел, была здесь и здесь, ни один из которых не является таким подробным, как то, что вы процитировали. Спасибо. - person makansij; 22.12.2015
comment
Я использовал следующий код. Это дает мне ошибку травления. Можете ли вы мне помочь с этим? Мой код: def dist2(a,b): return jaccard(a,b) knnobj = NearestNeighbors(n_neighbors=6, алгоритм='auto',metric=lambda a,b: dist2(a,b)).fit(my_Data ) PicklingError: Не удается выбрать ‹тип «функция»›: поиск атрибута встроенный. Функция не удалась - person csalive; 15.01.2018