KNN交叉验证,找出合适的K值


在KNN里,通过交叉验证,我们即可以得出最合适的K值。它的核心思想无非就是把一些可能的K逐个去尝试一遍,然后选出效果最好的K值

交叉验证的第一步是把训练数据进一步分成训练集和验证集。

为什么这么做?

道理其实很简单,因为我们需要一种评估的机制来选出最好的K值。那具体用什么数据来评估呢? 就是验证集! 因为测试数据是用来一次性测试的。比如上线前来测试是否满足上线的条件,但测试数据不能用于指导模型的训练。

常用的交叉验证技术叫做K折交叉验证(K-fold Cross Validation)。 我们先把训练数据再分成训练集和验证集,之后使用训练集来训练模型,然后再验证集上评估模型的准确率。举个例子,比如一个模型有个参数叫alphaα,我们一开始不清楚要选择0.1还是1,所以这时候我们进行了交叉验证:把所有训练集分成K块,依次对每一个alphaα值评估它的准确率。

一般情况下数据量较少的时候我们取的K值会更大,为什么呢?

因为数据量较少的时候如果每次留出比较多的验证数据,对于训练模型本身来说是比较吃亏的,所以这时候我们尽可能使用更多的数据来训练模型。由于每次选择的验证数据量较少,这时候K折中的K值也会随之而增大,但到最后可以发现,无论K值如何选择,用来验证的样本个数都是等于总样本个数。

最极端的情况下,我们可以采用leave_one_out交叉验证,也就是每次只把一个样本当做验证数据,剩下的其他数据都当做是训练样本。

 

从零写交叉验证

1.导入模块

import numpy as np from sklearn import datasets from sklearn.neighbors import KNeighborsClassifier from sklearn.model_selection import KFold  #主要用于K折交叉验证

 

2.导入数据

# 导入iris数据集
iris=datasets.load_iris() X=iris.data y=iris.target print(X.shape,y.shape) # 定义我们想要搜索的K值(候选集),这里定义8个不同的值
ks=[1,3,5,7,9,11,13,15]

结果:

(150, 4) (150,)

3.应用

# 例:进行5折交叉验证,KFold返回的是每一折中训练数据和验证数据的index # 假设数据样本为:[1,3,5,6,11,12,43,12,44,2],总共10个样本 # 则返回的kf的格式为(前面的是训练数据,后面的是验证数据): # [0,1,3,5,6,7,8,9],[2,4] # [0,1,2,4,6,7,8,9],[3,5] # [1,2,3,4,5,6,7,8],[0,9] # [0,1,2,3,4,5,7,9],[6,8] # [0,2,3,4,5,6,8,9],[1,7]
kf =KFold(n_splits=5,random_state=2001,shuffle=True) # 保存当前最好的K值和对应的准确值
best_k=ks[0] best_score=0 # 循环每一个K值
for k in ks: curr_score=0 for train_index,valid_index in kf.split(X): #每一折的训练以及计算准确率
        clf=KNeighborsClassifier(n_neighbors=k) clf.fit(X[train_index],y[train_index]) curr_score=curr_score+clf.score(X[valid_index],y[valid_index]) #求5折的平均准确率
    avg_score=curr_score/5
    if avg_score>best_score: best_k=k best_score=avg_score print("现在的最佳准确率:%.2f"%best_score,"现在的最佳K值 %d"%best_k) print("最终最佳准确率:%.2f"%best_score,"最终的最佳K值 %d"%best_k)

结果:

现在的最佳准确率:0.96 现在的最佳K值 1
现在的最佳准确率:0.96 现在的最佳K值 1
现在的最佳准确率:0.97 现在的最佳K值 5
现在的最佳准确率:0.98 现在的最佳K值 7
现在的最佳准确率:0.98 现在的最佳K值 7
现在的最佳准确率:0.98 现在的最佳K值 7
现在的最佳准确率:0.98 现在的最佳K值 7
现在的最佳准确率:0.98 现在的最佳K值 7
最终最佳准确率:0.98 最终的最佳K值 7

 

直接使用sklearn来实现同样的逻辑,只需要调用即可以实现K折交叉验证

from sklearn import datasets from sklearn.neighbors import KNeighborsClassifier from sklearn.model_selection import GridSearchCV  #通过网络方式来获取参数

# 导入iris数据集
iris2=datasets.load_iris() X2=iris2.data y2=iris2.target print(X2.shape,y2.shape) # 设置需要搜索的K值,'n_neightbors'是sklearn中KNN的参数
parameters={'n_neightbors':[1,3,5,7,9,11,13,15]} knn=KNeighborsClassifier()#注意:这里不用指定参数

# 通过GridSearchCV来搜索最好的K值。这个模块的内部其实就是对每一个K值进行评估
clf=GridSearchCV(knn,parameters,cv=5)  #5折
clf.fit(X2,y2) # 输出最好的参数以及对应的准确率
print("最终最佳准确率:%.2f"%clf.best_score_,"最终的最佳K值",clf.best_params_)

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM