在 Python scikit-learn 上使用自定义权重的最近邻

Nearest Neighbor using customized weights on Python scikit-learn

晚安,

我想使用最近邻模型进行非均匀权重回归。我在User Guide里面看到可以在模型的声明中使用weights='distance',这样权重就会和距离成反比,但是得到的结果不是我想要的。

我在 Documentation 中看到我可以为预测中使用的权重(给定距离)使用一个函数,所以我创建了以下函数:

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()

我不明白我做错了什么。在 Documentation 上写着我的函数应该有一个距离数组作为参数并且应该 return 等效权重。我做错了什么?

提前致谢。

我对这种类型的回归知之甚少,但传递给它的距离很可能是一个二维数据结构,这对所有成对距离都有意义。

你为什么不在你的自定义函数中加入一个小的预告打印语句来打印 distancesdistances.shape

@Jeff H 的提示让我找到了答案。

该函数的输入参数是一个二维numpy数组distances,形状为(predictions, neighbors),其中:

  • predictions 是所需预测的数量(当您调用 knn.predict(X_1, X_2, X_3, ...);
  • neighbors,使用的邻居数量(在我的例子中,n_neighbors=50)。

每个元素distances[i, j]表示i预测的距离,距离j最近的邻居(越小j,距离越小)。

该函数必须return一个与输入数组具有相同维度的数组,权重对应于每个距离。

我不知道这是不是最快的方法,但我想到了这个解决方案:

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