KNN即k近邻算法 k nearest neighbors algorithm.knn算法是以离预测点距离最近的k个点中类别中最多的元素作为预测结果。特点是不需要训练。因此算法简单。
基本要素:
1.k值的选择
2.距离的度量
3.分类决策原则
k值的选择
是knn算法中的一个超参数,也就是在模型建立前需要指定的参数。k值大,会导致近似误差过大,而k过小,则会过拟合。
距离的度量
通常用p函数,其中这个p是KNN算法中的另一个超参数。
p=1时,称为1范数,也叫曼哈顿距离,p=2,称为2范数,也就是经典的欧式距离。
分类决策原则
多数表决
KNN算法是希望找到最佳的k和p,使得预测准确率能够最高。实现这一点还需要用到网格搜索。其实也就是for循环。
算法:
# -*- coding:utf-8 -*-
# 加入assert断言,是为了判断语句是否合法,这样做更为友好,当不写断言,出现错误,不知道出现在那里
import numpy as np
import matplotlib.pyplot as plt
from collections import Counter
import pandas as pd
class KNNClassifier:
'''KNN算法'''
def __init__(self,k):
'''初始化'''
assert k >= 1,\
"k must be valid."
self._x_train = None # 定义_x_traion和_y_train 属性
self._y_train = None
self.k = k # k 属性
def fit(self, x_train, y_train):
'''训练'''
# assert x_train.shape[0] == y_train.shape[0], \
# "x's row ==y's row"
assert self.k <= x_train.shape[0],\
"the num of k must less than x_train's row num"
self._x_train= x_train # 把用户输入的训练数据导入到这两个属性
self._y_train= y_train
print(self)
return self
def predict(self,x_predict):
'''给定x_predict预测'''
self.x_predict = x_predict # 定义self.x_predict 属性
assert self._x_train is not None and self._y_train is not None,\
"Before predict must be fitted."
assert x_predict.shape[1] == self._x_train.shape[1],\
"the features must equal."
y_predict=np.array([self._predict(x=i) for i in self.x_predict])
# print(y_predict)
return y_predict
# 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import *
def _predict(self,x):
'''给定单个待预测值'x',求其预测值'''
distance = np.array([np.sum((x_train - x) ** 2) ** 0.5 for x_train in self._x_train ])
near = np.argsort(distance)
top_k = [self._y_train[i] for i in near[:self.k]]
votes = Counter(top_k)
return votes.most_common(1)[0][0]
# 预测准确度
def accuracy(self,x_test,y_test):
y_predict=self.predict(x_predict=x_test)
return sum(y_predict==y_test)/len(y_test)
def __repr__(self):
return "KNN(k=%d)" % self.k
对于超参数k,可以选择网格搜索和交叉验证的方式得到。
可以参考sklearn中的GrideSearch和Cross_Validation。最好是自己设计。