Ближайший сосед с использованием настраиваемых весов на Python scikit-learn - PullRequest
0 голосов
/ 11 июля 2020

Спокойной ночи,

Я хотел бы использовать модель ближайшего соседа для регрессии с неоднородными весами. Я видел в Руководстве пользователя , что я могу использовать weights='distance' в объявлении модели, и тогда веса будут обратно пропорциональны расстоянию, но результаты, которые я получаю, были не такими, как я хотел.

Я видел в Документации , что я могу использовать функцию для весов (с учетом расстояний), используемых в прогнозе, поэтому я создал следующую функцию:

from sklearn.neighbors import KNeighborsRegressor
import numpy
nparray = numpy.array

def customized_weights(distances: nparray)->nparray:
    for distance in distances:
        if (distance >= 100 or distance <= -100):
            yield  0

        yield (1 - abs(distance)/100)

И объявили метод так:

knn: KNeighborsRegressor = KNeighborsRegressor(n_neighbors=50, weights=customized_weights ).fit(X_train, y_train)

До этой части все работает нормально. Но когда я попытался предсказать с помощью модели, я получил ошибку:

  File "knn_with_weights.py", line 14, in customized_weights
    if (distance >= 100 or distance <= -100):
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Я не понял, что сделал не так. В Документации написано, что моя функция должна иметь массив расстояний в качестве параметра и должна возвращать эквивалентные веса. Что я сделал не так?

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 12 июля 2020

Совет @ Jeff H направил меня к ответу.

Входным параметром этой функции является двумерный numpy массив distances с формой (predictions, neighbors) , где:

  • прогнозы - это количество желаемых прогнозов (когда вы вызываете knn.predict(X_1, X_2, X_3, ...);
  • соседей, количество используемых соседей (в моем случае n_neighbors = 50).

Каждый элемент distances[i, j] представляет расстояние для прогноза i от j ближайшего соседа (меньший j, меньшее расстояние).

функция должна возвращать массив с теми же размерами, что и входной массив, с весом, соответствующим каждому расстоянию.

Я не знаю, является ли это самым быстрым способом, но я придумал следующее решение:

def customized_weights(distances: nparray)->nparray:

    weights: nparray = nparray(numpy.full(distances.shape, 0), dtype='float')
# create a new array 'weights' with the same dimension of  'distances' and fill 
# the array with 0 element.
    for i in range(distances.shape[0]): # for each prediction:
        if distances[i, 0] >= 100: # if the smaller distance is greather than 100, 
                                   # consider the nearest neighbor's weight as 1 
                                   # and the neighbor weights will stay zero
            weights[i, 0] = 1
                                   # than continue to the next prediction
            continue

        for j in range(distances.shape[1]): # aply the weight function for each distance

            if (distances[i, j] >= 100):
                continue

            weights[i, j] = 1 - distances[i, j]/100

    return weights
0 голосов
/ 11 июля 2020

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

Почему бы вам не добавить небольшую инструкцию print в свою пользовательскую функцию, чтобы напечатать и distances, и distances.shape

...