1、什么是KNN算法
KNN算法指N-NearestNeighbors,K最近邻算法,采用测量不同特征值之间的距离方法进行分类
既可以用做分类器也可以用做回归模型
2、工作原理
存在一个样本数 据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。 最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。
k一般取奇数(odd number)
3、优缺点
优点:精度高、对异常值不敏感、无数据输入设定
缺点:计算复杂度高、空间复杂度高
适用数据范围:数值型和标称型
4、需要考虑的几个问题
1.把一个物体表示成向量
这个过程也叫特征工程 Feature Engineering,模型的输入一定是数量化的信息,这就需要把实际需求表示成向量/张量/矩阵的形式,如找出一个人的可数量化的特征,性别、年龄、身高、体重、收入、婚否等特征就可以表示成一个向量,而图片这样的信息是不能直接存储在计算机表示的,图片一般是以矩阵的形式存储,每一个元素代表一个rgb,这样就能存储在计算机
2.标记好每个物体的标签
KNN算法首先要有一组带标签的数据,可能是人为手动打的标签也可能是机器自动打的标签
3.计算两个物体之间的距离/相似度
一般采用欧式距离计算两个物体之间的距离
代码示例
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
# datasets 三分类问题,用datasets库自动生成一组数据
iris = datasets.load_iris()
#特征,矩阵
X = iris.data # X是一个D*N 的矩阵 D:样本的数量 N 维度
y = iris.target # 标签
print(x,y)
# 把样本分成训练数据和测试数据
train_X,test_X,train_y,test_y = train_test_split(X,y,random_state = 2003)
#print(train_X)
# 构建KNN模型, K值为3、 并做训练
clf = KNeighborsClassifier(n_neighbors=3)
clf.fit(train_X, train_y)
# 计算准确率
from sklearn.metrics import accuracy_score
#正确的个数
correct = np.count_nonzero((clf.predict(test_X)==test_y)==True)
#accuracy_score(y_test, clf.predict(X_test))
#正确的个数/总数 = 正确率
print ("Accuracy is: %.3f" %(correct/len(test_X)))
4.选择合适的K
k是超参数
参数类型:
1)模型参数Model Parameter,是通过训练数据学习获得;
2)超参数HyperParamerter,在模型之外的参数,相当于一个开关,调参指的就是调整超参数
决策边界:如60分及格,小于60的即不及格,大于等于60的就是及格,这个问题中60就是决策边界。
决策边界决定"“线性分类器"或"非线性分类器”,决策边界过于陡峭或锋利都不是理想的决策边界,会出现过拟合的问题。理想的决策的边界比较平缓,这样才会使得准确率高、稳定。
如何寻找决策边界?
交叉验证。随着k的增加,决策边界会变得越来越平滑,通过交叉验证可以选择合适的K,也就是"调参".
把训练数据进一步分成训练数据TrainingData和验证数据Validation Data,选择在验证数据里最好的超参数组合。
- 5折交叉验证(5-fold Cross Validation)
过程:
0 选择k为3或5等
1 将训练数据平均分成5份
2 每次选其中一份作为验证数据,其余4分作为训练数据
3用训练数据训练,训练完成后去验证数据去验证得到准确率
4全部训练并验证完成后5个准确率相加除以5的到平均准确率
5比较不同的k值获取的平均准确率的高低,取最高准确率的K值
其中5折也可以选择其他值,如10就是将训练数据平分成10份
注意:千万不能用测试数据聊调参,数据量越少,可以适当增加折数
5.KNN中需要考虑的点
数据特征的量纲不能差距太大,否则小值的特征会起不到作用,如[1,1000]这样的值
如何解决此类问题?采用特征的缩放。
方式有1线性归一化(Min-max Normalization)
如把(0,6000)缩放到(0,1)
转化公式:Xnew = (X - min(X)) / (max(X)-min(X))
2标准差标准化:把特征映射到(0,1)之间
mean(X) :X的平均值
std(X) : X的标准差
Xnew = (X-mean(X)) / std(X)