KNN代码实现

实现细节

  1. 函数_knn()

    partial为functools中的函数,可以实现参数的分步传递

    
    from functools import partial
    def substract(x,y):
    return x-y
    f = partial(substract,4)#把4传递给x
    f(10) #把10传递给y,最终结果为-6

    argpartition实现第k个元素为它最终的排序位置,前面的元素比第k个元素小,及第k个元素为第k小的元素,前面的元素均比它小,该函数返回的是索引。

  2. 函数_predict()

    topk_ind = self._knn(x),与x距离排在前k为的索引

    topk_y = self.Y[topk_ind],取得响应的目标值

    return np.argmax(np.bincount(topk_y)),返回topk_y中出现最多次的topk_y

    # bincount()
    x=np.array([1,1,2,3,0,5])
    np.bincount(x)
    # array[1,2,1,1,0,1]
    # 上面数组中的第i个位置为k,即i在原数组中有k个,因为原数组中没有4,故上面数组第4个位置为0
  3. 关于np中的axis

    axis=i,即第i维是未定参数,如一个x[2,3]的矩阵,如果对axis=1进行某种操作,相当于将第0维确定的值进行操作,即:x[0,:]和x[1,:]作为形参传递

    a=np.ones(3,4)
    np.sum(a,axis=1)
    # Out[6]: array([4., 4., 4.])
    # 相当于依次对a[0,:],a[1,:],a[2,:]进行求和
    np.sum(a,axis=0)
    # Out[7]: array([3., 3., 3., 3.])
class KNN:
    def __init__(self, k=1, distance_func="l2"):
        self.k = k
        if distance_func == 'l2':
            self.distance_func = lambda x, y: np.linalg.norm(x - y)
        else:
            self.distance_func = distance_func

    def _knn(self, x):
        dis = np.apply_along_axis(partial(self.distance_func, y=x), axis=-1, arr=self.X)
        topk_ind = np.argpartition(dis, self.k)[:self.k]
        return topk_ind

    def _predict(self, x):
        topk_ind = self._knn(x)
        topk_y = self.Y[topk_ind]
        return np.argmax(np.bincount(topk_y))

    def fit(self, X, Y):
        self.X = X
        self.Y = Y
        self.k = min(self.k, len(self.X))

    def predict(self, X):
        return np.apply_along_axis(self._predict, axis=-1, arr=X)

评论区 0