Scikit-learn: как определить параметр метрики расстояния для поиска в сетке

У меня есть следующий фрагмент кода, который пытается выполнить поиск сетки, в которой один из параметров сетки является метрикой расстояния, которая будет использоваться для алгоритма KNN. В приведенном ниже примере произойдет сбой, если я использую метрики расстояний "wminkowski", "seuclidean" или "mahalanobis".

# Define the parameter values that should be searched
k_range    = range(1,31)
weights    = ['uniform' , 'distance']
algos      = ['auto', 'ball_tree', 'kd_tree', 'brute']
leaf_sizes = range(10, 60, 10)    
metrics = ["euclidean", "manhattan", "chebyshev", "minkowski", "mahalanobis"]

param_grid = dict(n_neighbors = list(k_range), weights = weights, algorithm = algos, leaf_size = list(leaf_sizes), metric=metrics)
param_grid

# Instantiate the algorithm
knn = KNeighborsClassifier(n_neighbors=10)

# Instantiate the grid
grid = GridSearchCV(knn, param_grid=param_grid, cv=10, scoring='accuracy', n_jobs=-1)

# Fit the models using the grid parameters
grid.fit(X,y)

Я предполагаю, что это потому, что я должен установить или определить диапазоны для различных параметров расстояния (например, p, w для "wminkowski" - WMinkowskiDistance). Расстояние "Минковского" может работать, потому что его параметр "p" имеет значение по умолчанию 2.

Итак, мои вопросы:

  1. Можем ли мы установить диапазон параметров для метрик расстояния для поиска по сетке, и если да, то как?
  2. Можем ли мы установить значение параметров для метрик расстояния для поиска в сетке, и если да, то как?

Надеюсь, вопрос ясен. ТИА

1 ответ

Решение

Я наконец получил ответ с помощью списка рассылки пользователей и разработчиков Scikit. Я помещаю сюда то, что я узнал, в надежде, что это поможет и другим.

Ответ на два вопроса выше: да. Вот пример кода, который я получил из списка рассылки:

params = [{'kernel':['poly'],'degree':[1,2,3],'gamma':[1/p,1,2],'coef0':[-1,0,1]},
          {'kernel':['rbf'],'gamma':[1/p,1,2]},
          {'kernel':['sigmoid'],'gamma':[1/p,1,2],'coef0':[-1,0,1]}]

Следует отметить две вещи:

  1. Вы можете перечислить набор параметров, для каждого набора вы можете разместить только то, что требуется для группы параметров. Это означает, что мы можем выбрать метрику и соответствующие параметры. Параметры именуются с помощью клавиш.

  2. Для каждого из ключей мы можем использовать список значений - каждая комбинация этих значений будет использоваться при поиске по сетке и передаваться соответствующей метрической функции.

Это все еще оставляет нас с проблемой: как мы передаем комбинацию параметров в метрику. Примечание: не все метрики могут использоваться алгоритмом, поэтому вы должны установить их вручную.

Теперь я покажу пример, который я просил выше:

{'metric': ['wminkowski'], 
                     'metric_params':[
                                {'w':np.array([2.0] * len(X.columns)),'p':1.0},   # L1
                                {'w':np.array([2.0] * len(X.columns)),'p':1.5},
                                {'w':np.array([2.0] * len(X.columns)),'p':2.0},   # L2
                                {'w':np.array([2.0] * len(X.columns)),'p':2.5},
                                {'w':np.array([2.0] * len(X.columns)),'p':3.5},
                                {'w':np.array([2.0] * len(X.columns)),'p':3.0}
                               ], 
                     'algorithm': ['brute', 'ball_tree'], 
                     'n_neighbors': list(k_range), 'weights': weights, 'leaf_size': list(leaf_sizes) } 

Обратите внимание на следующее:

  1. 'wminkowski' работает только с ['brute', 'ball_tree'] алгоритмы.
  2. Мы должны использовать список словарей в 'metric_params' Для того, чтобы перечислить все возможные комбинации параметров (я не нашел способ автоматизировать это).
  3. В приведенном выше случае я был вынужден использовать массив NumPy, потому что преобразование не было сделано неявно (в противном случае мы получаем исключение)

Кто-нибудь знает лучший способ сделать это, пожалуйста, прокомментируйте.

Другие вопросы по тегам