knn是一个很神奇的算法,是不需要进行训练的,直接进行预测,那它是怎么进行预测的呢?
首先我们来看一幅图:
假设我们有一个训练集x_train和y,我们要预测x_test中的数据的类别。
在knn里是怎么做的呢?
我们先固定x_test在一个具体的行上,我们用字母i表示,然后我们依次和x_train的每一行计算欧氏距离,然后我们就可以得到一堆的欧氏距离,紧接着我们对这一堆欧式距离进行从小到大排序,取其中前k个,然后再统计k个当中出现次数最多的一行(x_train中),这一行就是我们预测的结果。以此类推我们就可以将测试集里的每一行进行预测出来。
这里还是有一个问题,假若k个中出现的最大次数存在次数相同的,我们该选择哪一个呢?该怎么处理呢?这里肯定需要调整k值了,根据类别的种类数我们来确定k。
附上人家的源码:
# coding:utf-8
import numpy as np
from mlfromscratch.utils import euclidean_distance
class KNN():
def __init__(self,k=5):
self.k = k
def predict(self, X_test, X_train, y_train):
y_predict = np.zeros(X_test.shape[0])
for i in range(X_test.shape[0]):
distances = np.zeros((X_train.shape[0], 2)) #测试的数据和训练的各个数据的欧式距离
for j in range(X_train.shape[0]):
dis = euclidean_distance(X_test[i], X_train[j]) #计算欧式距离
label = y_train[j] #测试集到的每个训练集的数据的分类标签
distances[j] = [dis, label]
# argsort()得到测试集到训练的各个数据的欧式距离从小到大排列并且得到序列,然后再取前k个.
k_nearest_neighbors = distances[distances[:, 0].argsort()][:self.k]
#利用np.bincount统计k个近邻里面各类别出现的次数
counts = np.bincount(k_nearest_neighbors[:, 1].astype('int'))
#得出每个测试数据k个近邻里面各类别出现的次数最多的类别
testLabel = counts.argmax()
y_predict[i] = testLabel
return y_predict