'''
k折交叉验证
k折交叉验证里面的k并不是Knn里面的k(eighbors)
在KNN里,通过交叉验证,我们即可以得出最合适的K值。
它的核心思想无非就是把一些可能的K逐个去尝试一遍,
然后选出效果最好的K值。
一般情况将K折交叉验证用于模型调优,找到使得模型泛化性能最优的超参值。
,找到后,在全部训练集上重新训练模型,并使用独立测试集对模型性能做出最终评价。
k折交叉验证
K折交叉验证(k-fold cross-validation)首先将所有数据分割成K个子样本,不重复的选取其中一个子样本作为测试集,其他K-1个样本用来训练。
共重复K次,平均K次的结果或者使用其它指标,最终得到一个单一估测。
这个方法的优势在于,保证每个子样本都参与训练且都被测试,降低泛化误差。其中,10折交叉验证是最常用的。
'''
import numpy as np
from sklearn.model_selection import KFold
x=['a','b','c']
kf=KFold(n_splits=3) # 三折交叉验证
#print(["%s%s"%(train,test) for train,test in kf.split(x)]) # [(array([1, 2]), array([0])), (array([0, 2]), array([1])), (array([0, 1]), array([2]))]
for train,test in kf.split(x):
print("%s%s"%(train,test))
'''
[1 2][0]
[0 2][1]
[0 1][2] 返回的是下标 而不是原值
'''
print('下面进行knn的交叉验证')
import numpy as np
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import KFold #用于k折交叉验证
#导入数据
iris=datasets.load_iris()
x=iris.data
y=iris.target
# print(x.shape,y.shape) (150, 4) (150,)
#Knn算法的预先给定一个范围,从中通过计算选取最优的一个
knn_n=[1,3,5,7,9,11,13,15] #不是k折交叉验证里面的k
'''
x=['a','b','c']
[1 2][0]
[0 2][1]
[0 1][2] 返回的是下标 而不是原值
'''
kf=KFold(n_splits=5,random_state=2001,shuffle=True) #若为True时,每次划分的结果都不一样,表示经过洗牌,随机取样的
best_k=knn_n[0] # 保存最好的k值
best_score=0
for k in knn_n:
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])
# 求一下每折验证后的平均准确率
avg_score=curr_score/5 # 前面定的是5折
if avg_score>best_score:
best_score=avg_score
best_k=k
print("当前n_neighbors:%d "%k,
"截止到当前最优n_neighbors:%d "%best_k,
"当前平均准确率:%.3f " % avg_score,
"截止到当前最优平均准确率:%.3f "%best_score)
print("全局n_neighbors:%d"%best_k,"全局最高平均准确率:%.3f"%best_score)
'''
当前n_neighbors:1 截止到当前最优n_neighbors:1 当前平均准确率:0.960 截止到当前最优平均准确率:0.960
当前n_neighbors:3 截止到当前最优n_neighbors:1 当前平均准确率:0.960 截止到当前最优平均准确率:0.960
当前n_neighbors:5 截止到当前最优n_neighbors:5 当前平均准确率:0.967 截止到当前最优平均准确率:0.967
当前n_neighbors:7 截止到当前最优n_neighbors:7 当前平均准确率:0.980 截止到当前最优平均准确率:0.980
当前n_neighbors:9 截止到当前最优n_neighbors:7 当前平均准确率:0.967 截止到当前最优平均准确率:0.980
当前n_neighbors:11 截止到当前最优n_neighbors:7 当前平均准确率:0.960 截止到当前最优平均准确率:0.980
当前n_neighbors:13 截止到当前最优n_neighbors:7 当前平均准确率:0.953 截止到当前最优平均准确率:0.980
当前n_neighbors:15 截止到当前最优n_neighbors:7 当前平均准确率:0.960 截止到当前最优平均准确率:0.980
全局n_neighbors:7 全局最高平均准确率:0.980
'''
#-----------------------------------以上是从0开始写的k折交叉验证 下面实际上我们可以直接使用sklearn来实现同样的逻辑,只需要调用即可以实现K折交叉验证------
#-----------------------------------以上是从0开始写的k折交叉验证 下面实际上我们可以直接使用sklearn来实现同样的逻辑,只需要调用即可以实现K折交叉验证------
#-----------------------------------以上是从0开始写的k折交叉验证 下面实际上我们可以直接使用sklearn来实现同样的逻辑,只需要调用即可以实现K折交叉验证------
#-----------------------------------以上是从0开始写的k折交叉验证 下面实际上我们可以直接使用sklearn来实现同样的逻辑,只需要调用即可以实现K折交叉验证------
from sklearn.model_selection import GridSearchCV #通过网格方式来搜索参数
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
#导入数据
iris=datasets.load_iris()
x=iris.data
y=iris.target
#设置n_neighbors的预选值
parameters={'n_neighbors':[1,3,5,7,9,11,13,15]}
knn=KNeighborsClassifier() #注意这里并没有指定n_neighbors 参数、
#通过GridSearchCV来搜索最好的k值 这个模块其实就是对每个n_neighbors进行评估
# GridSearchCV 官网 :https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html#sklearn.model_selection.GridSearchCV
# GridSearchCV 参考:
# GridSearchCV 参考:
clf=GridSearchCV(knn,parameters,cv=5) #5折交叉验证
clf.fit(x,y)
#输出最好的参数以及准确率
print("最有准确率:%.3f"%clf.best_score_,"最优的n_neighbors:",clf.best_params_)
'''
最有准确率:0.980 最优的n_neighbors: {'n_neighbors': 7}
'''